Подсчет ссылок в PHP - PullRequest
       28

Подсчет ссылок в PHP

2 голосов
/ 02 января 2009

Я бы хотел реализовать функцию кэширования базы данных в PHP на основе количества ссылок. Например, код для доступа к записи в таблице foo с идентификатором 1 может выглядеть следующим образом:

$fooRecord = $fooTable->getRecord(1);

При первом вызове $fooTable выбирает соответствующую запись из базы данных, сохраняет ее во внутреннем кеше и возвращает. Любые последующие вызовы getRecord(1) будут возвращать другую ссылку на тот же объект в памяти. $fooRecord сигнализирует $fooTable, когда он разрушается, и если нет оставшихся ссылок, он сохраняет все изменения обратно в базу данных и удаляет их из кэша.

Проблема в том, что управление памятью в PHP абстрагируется от деталей о количестве ссылок. Я искал расширение PECL и Google для этого, но не нашел результатов. Итак, вопрос № 1: существует ли такое расширение?

В альтернативном подходе $ fooTable возвращает супер-подлый поддельный объект. Он притворяется записью, пересылая __call(), __set() и __get(), а его конструктор и деструктор предоставляют соответствующие хуки для подсчета ссылок. Тесты, отлично работает, разве что ломает намеки на тип. Все мои методы, которые ожидали объект FooRecord, теперь получают объект Sneaky, или, возможно, FooSneaky, если мне хочется создать пустой подкласс Sneaky для каждой из моих таблиц , чего у меня нет. Кроме того, я боюсь, что это запутает программистов по обслуживанию (таких как я).

Вопрос № 2: Есть ли другой подход, который я пропустил?

Ответы [ 4 ]

2 голосов
/ 03 января 2009

Для php5, просто используйте деструктор в классе записи.

class Table {
    /* [...] */
    protected $record_cache = array();
    public function getRecord($id) {
        if(isset($this->record_cache[$id]) return $this->record_cache[$id];

        $r = $db->getRecord($id);
        if($r instanceof Record) {
            $this->record_cache[$id] = $r;
        }
        return $r;
    }

    public function _unregister($id) {
        unset($this->record_cache[$id]);
    }
}

class Record {
    /* [...] */
    function __destruct() {
        this->table->_unregister($this->id);
    }
}

Если вы не хотите использовать публичный метод для этого в Таблице, вы, вероятно, можете использовать какой-нибудь трюк с обратным вызовом или другой умный взлом:)

1 голос
/ 03 января 2009

Стандартный Интернет Справочный Форум Предостережение: Возможно, я не до конца понимаю, что вы пытаетесь сделать.

Я не уверен, что ваша идея вписывается в цикл запросов / ответов PHP. Традиционно (CGI, mod_php) жизненный цикл PHP-запроса выглядит примерно так:

  1. Пользователь делает HTTP-запрос на страницу PHP
  2. Страница PHP (и все включенные файлы) превращаются в opt-код
  3. Опт-код выполнен
  4. По завершении цикла все выбрасывается

Это было одной из причин, по которой PHP так хорошо работал на рынке с менее опытными программистами. Даже самое ужасно закодированное приложение может повесить сервер только в течение жизненного цикла запроса. Есть некоторые параллели с HTTP; PHP (вроде) построен так, что каждый запрос ничего не знает о любом другом запросе.

Я не очень хорошо знаком с методами развертывания fast-cgi (используемыми, например, в Zend Platform), но, насколько я понимаю, несколько процессов PHP будут зависать в памяти для обработки запросов, а затем возникает какое-то волшебное вуду это убьет и повторно вызовет процессы по мере необходимости.

Суть всего этого заключается в том, что идея отслеживания того, где объекты PHP находятся в памяти по счетчику ссылок, не имеет смысла в модели запросов PHP, поэтому вы не найдете там много. Кэширование в PHP пользовательской среде означает использование отдельной программируемой системы в соответствии с memcached или APC для обработки деталей управления памятью для вас. Кэширование абстрагируется в простую систему хранения пар ключ / значение.

Тем не менее, если вы продвинетесь вперед со своим подходом, мне было бы интересно увидеть конечные результаты:)

1 голос
/ 02 января 2009

Вы смотрели на простые реализации кеша в PHP? например, используя что-то вроде Zend_Cache :

public function getRecord($id) {
     $cache = $this -> getCache(); //Retrieves an instanced Zend_Cache object or creates one
     $key = $this -> _name . $id; //_name is the table name and with the ID create a unique key

     if(!$result = $cache->load($key)) { 
         //Cache miss, query database
         $result = $this -> query(...);
         $cache->save($result, $key);
     }
     return $result;
}

Вы можете легко реализовать эту функцию кэширования самостоятельно или использовать готовый компонент, такой как Zend.

0 голосов
/ 02 января 2009

Звучит так, будто вы хотите получить ORM с фреймворком или API. Я не использовал его, но знаю, что ADOdb делает это. В качестве альтернативы CakePHP использует ORM и может быть хорошим вариантом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...