Собственно кеширование вывода MVC фреймворков является абсолютно классической и рутинной задачей, все фреймворки в той или иной степени реализуют его, тут я в общих словах накидаю разработанную мной методологию.
данная система подразумевает что фреймворк работает с БД в эксклюзивном режиме — т.е, грубо говоря админка данных реализована в текущем проекте и в базу ручками не лазят.
Для затравки, укажу используемые мной инструменты и укажу направдение в котором я двигался:
Система кеширования — просто синглтон который по ключу из драйвера получает значение — все просто как молоток
Теги кеша — базовый наследуемый класс Tag:
Теги реализуются наследованием данного класса и реализацией конструктора «по вкусу».
Теперь можно некоторую запись в кеше пометить набором тегов (тут предполагается что читатель включит фантазию) и сделав clear() тега принудительно сделать все записи кеша содержащие данный тег — не валидными.
Отложенные запросы отлично реализуются с помощью ORM Propel 1.3 — все что вам нужно это запихивать в шаблон объект реализующий SPL Iterator и включающий сформированный объект класса Propel Criteria ну и всякая OOП магия пыха тоже полезна, в данном случае.
На тот-же Propel, путем написания своих билдеров в сущности запихиваются триггеры обнуления тегов:
В качетве шаблонизатора использую PHPTAL, к нему пишется кеширующий триггер. Контроллеры имеют примерно следующий вид:
А шаблон:
Вот теперь, при первом запросе сформированное содержимое елемента div попадет в кеш c тегом
Все описанное выше — работает в реальном фреймворке и если хабрасообщество меня приймет то думаю буду писать еще.
Что потребуется
- Нужна реализация общего механизма кеша, но не совсем обычная — секрет поддержка тегов
- Нужен базовый ORM в каком-либо виде, все что от него требуется это на все сущности, на сохранение и удаление повесить определенные события
- Нужна поддержка отложенных запросов — основная идея в том что запрос формируется в контроллере но выполняется при разборе шаблона
- Быстрый компилируемый шаблон с поддержкой кеширования — тут от шаблонизатора требуется что-бы он мог полностью заменять обработку куска шаблона содержимым кеша по указанному ключу
Ограничения
данная система подразумевает что фреймворк работает с БД в эксклюзивном режиме — т.е, грубо говоря админка данных реализована в текущем проекте и в базу ручками не лазят.
Реализация
Для затравки, укажу используемые мной инструменты и укажу направдение в котором я двигался:
Система кеширования — просто синглтон который по ключу из драйвера получает значение — все просто как молоток
Теги кеша — базовый наследуемый класс Tag:
class Tag { function __contruct($name) { $this->name = $name; } public function buildKey() { return sprintf('tag_%s_%s', get_class($this), $this->name); } public function clear() { $ver = microtime(true).'.'.rand(0, 1000000); Cache::GetInstance()->update($this->buildKey(), $ver); } }
Теги реализуются наследованием данного класса и реализацией конструктора «по вкусу».
Теперь можно некоторую запись в кеше пометить набором тегов (тут предполагается что читатель включит фантазию) и сделав clear() тега принудительно сделать все записи кеша содержащие данный тег — не валидными.
Отложенные запросы отлично реализуются с помощью ORM Propel 1.3 — все что вам нужно это запихивать в шаблон объект реализующий SPL Iterator и включающий сформированный объект класса Propel Criteria ну и всякая OOП магия пыха тоже полезна, в данном случае.
На тот-же Propel, путем написания своих билдеров в сущности запихиваются триггеры обнуления тегов:
class A { function save(PropelPDO $con) { .... $tag1 = new TagEntity(APeer::CLASS_NAME); $tag1->clear(); if (!$this->isNew()) { $tag2 = new TagPk(APeer::CLASS_NAME, $this->getPrimaryKey()); $tag2->clear(); } .... } }
В качетве шаблонизатора использую PHPTAL, к нему пишется кеширующий триггер. Контроллеры имеют примерно следующий вид:
function executeAction(Context $context) { $context->addTag('test_tag1', new TagEntity(APeer::CLASS_NAME)); // описываем тег и добавляем ему метку в контексте $context->as = APeer::Lazy()->descByDate()->limit(10); // готовим выборку $this->renderTemplate('template_name', $context); // рендерим шаблон - да такой у меня API }
А шаблон:
..... <div phptal:id="test_tag1"> <ul> <li tal:repeat="a as" tal:content="a/getTitle" /> </ul> </div> .....
Вот теперь, при первом запросе сформированное содержимое елемента div попадет в кеш c тегом
new TagEntity(APeer::CLASS_NAME)
, определенным в контроллере (магические триггер щаблонизатора) и пока не будут произведены какие-либо изменения таблицы, описываемой APeer, будет браться из кеша и запросов в БД не будет совсем.Вместо заключения
Все описанное выше — работает в реальном фреймворке и если хабрасообщество меня приймет то думаю буду писать еще.