вторник, 13 декабря 2011 г.

Кэширование ORM в Kohana


Потратил много времени на обнаружение неочевидной особенности поведения системы кэширования объектов, получаемых из базы с использованием встроенной системы ORM Kohana в случае, если в свойствах модели не указано явно название таблицы, ей соответствующей.
Если вы инициализируете значение $_table_name ORM-модели в ее конструкторе (как в примере ниже):
class Model_Foo extends ORM
{
protected $_db = 'default';
protected $_primary_key = 'id';
protected $_primary_val = 'name';
...
public function __construct($id = NULL)
{
$this->_table_name = 'foo_table';
...
parent::__construct($id);
}
...
}

, то при попытке загрузить закэшированные данные с помощью конструкции вида:
   $foos = ORM::factory('foo')->cached(7200)->find_all();
вы получите, увы, вовсе не закэшированный результат, а вполне себе актуальные данные (которые, конечно же, будут получены ценой запроса к БД, которого вы хотели избежать)
Такое поведение Kohana обусловлено тем, что при чтении объекта из кэша и его последующей корректной десериализации подгружается файл с описанием класса вашей модели Model_Foo, однако его конструктор не вызывается и, соответственно, имя таблицы не инициализируется. Так как поля таблицы в модели не описаны, Kohana пытается загрузить список полей из таблицы, соответствующей названию модели в множественном числе - для примера выше это `foos`. Если такой таблицы в базе данных не находится, то генерируется исключение, которое интерпретируется системой кэширования как признак поврежденого кэша и обрабатывается втихую - возвращая NULL вместо данных. В результате данные загружаются каждый раз из базы данных, несмотря на то, что присутствуют в кэше.
Таким образом, явное указание $_table_name необходимо в тех моделях, выборки для которых вы хотите хранить в кэше и успешно доставать оттуда же.
Хочу особенно отметить, что при загрузке и десериализации объекта из кэша Kohana для него не вызывается автоматически конструктор. Это необходимо учитывать и инициализировать свойства (которые при обычной загрузке устанавливаются в конструкторе) при обращении к методам загруженного из кэша объекта, если они (методы) эти свойства используют.

UPD: как мне подсказали знающие люди на форуме Kohana, если в модели вместо метода __construct()   использовать метод __initialize(), описанных проблем при десериализации не возникает, так как этот метод, в отличие от конструктора, в данной ситуации вызывается.

Комментариев нет:

Отправить комментарий

Напишите что-нибудь по теме