Мне недавно в блоге задали вопрос о применении ArrayAccess. Просто как замену массивам — глупо, тем более теряется производительность. Итак, для этого у нас две основные причины — set/get должны как-то влиять на значение переменных, вторая — объект может использовать данные помещённые в нём для других методов.
Рассмотрим примеры. У нас есть класс для работы с таблице из базы данных как с объектом.
class User extends ArrayObject { function offsetSet($key, $value) { $value = mysql_escape_string($value); if ($key) { $this->array[$key] = $value; } else { $this->array[] = $value; } } function offsetGet($key) { if ( array_key_exists($key, $this->array) ) { return htmlspecialchars($this->array[$key]); } } function getHtml($key) { if ( array_key_exists($key, $this->array) ) { return $this->array[$key]; } } function getFio() { return $this->array['firstName'] . ' ' . $this->array['lastName'] ; }
// много много кода ......... }
Что бы сделали?
Изменили наш сэттер, теперь присвоенное значение можно смело вставлять в базу данных, не боясь sql injection. (это скорее силиконовый пример).
$user = new User();
$user[‘login’] = ‘test » evil code’;
$user->save();
Изменили геттер, чтобы данные можно было вставлять в шаблон, не боясь xss и проблем с поехавшей вёрсткой.
$user = new User(666); //login -> <script>alert(‘HELP ME’);</script>
<p><?=$user[‘login’]?></p>
При этом с помощью специального опасного метода $user->getHtml(‘login’) мы имеем возможно вставлять и html код, но уже не позабыв об экранировании, а злонамеренно, чтобы навредить надоедливому заказчику :).
Ну и добавили новый метод, позволяющий получить сразу имя и фамилию $user->getFio().
вот это другое дело, элегантно 🙂
На мой взгляд использовать такой подход для работы с БД это сомнительное удовольствие:)
На мой взгляд код
$user = new User();
$user[‘login’] = ‘test » evil code’;
$user->save();
не очень удобен, было бы удобнее пользоваться старым добрым сетом:
$user = new User();
$user->set(‘login’ ,’test » evil code’)
->set(‘password’,’123123′)
->save();
А вот для класса Registry и т.п. такой подход довольно удобен..
я же написал как раз, что силиконовый пример, он не подходит во многом благодаря тому, что мы получим не тот результат при get
$user[‘login’] = «test ‘ evil code»;
echo $user[‘login’]; // вернёт «test \’ evil code
Оу да.. не обратил внимание… А так в целом довольно просто и понятно)
ps А ты так всегда вредишь «надоедливому заказчику»? 😉
скорее надоедливым программистам 😉
define(‘true’, false) — счастливого дебагинга.
не буду надоедать и не скажу, что вроде TRUE и есть константа, а их нельзя переопределять :))
ps а идея хорошая:)
Это с башорга)
к вопросу о вчерашних скриптостраданиях. Только что кодер знакомый прислал, нашёл в коде программы, написанной уволенным коллегой незадолго до ухода:
#define TRUE FALSE //счастливой отладки суки
* ****** такого извращённого юмора ещё не встречал
Пруф: _http://bash.org.ru/quote/268036
Наверное лучше бы заменить:
array_key_exists($key, $this->array)
на:
isset($this->array[$key])
Как считаешь?
нет, это не равноценные конструкции, array_key_exists ищет ключ каким бы не было его значение, а isset ищет только если это значение не равно NULL.
Если, чесно, я сам обычно пользуюсь isset или empty, т.к. в большинстве случаев важно именно значение хранящееся в переменной, а не тупо его наличие.