2010
02.01

Мне недавно в блоге задали вопрос о применении 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().

Похожие posts:

  1. SPL в PHP: ArrayObject
  2. Смешиваем singleton и registry
  3. Flash сообщения 2
  4. Паттерн: Registry
  5. Работа с формами

6 комментариев

Прокомментировать
  1. вот это другое дело, элегантно :)

  2. На мой взгляд использовать такой подход для работы с БД это сомнительное удовольствие:)
    На мой взгляд код
    $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) – счастливого дебагинга.

  3. не буду надоедать и не скажу, что вроде TRUE и есть константа, а их нельзя переопределять :) )

    ps а идея хорошая:)