Автор оригинала: HraKK
Смотри ZF_Cache там есть все.
Согласен. Вещь действительно сильная.
Кстати с аналогичной проблемой недавно сталкивался, и вот что подумал.
Например, есть страница какой-то новости. Обычно делается так. Если пользователь неавторизован - на странице выводится форма авторизации. Если пользователь авторизован, и обладает правом редактирования - то показывать административные ссылки (редактировать, удалить и пр.), персональное меню и пр.
Если такую страницу кэшировать по url + uid - будет расти избыточность объема кеша.
В ряде систем предлагается делать т.н. "дырки в кэше". Подобные решения можно наблюдать в cakePHP, Smarty и пр.
Возник вопрос. Как сделать малой кровью такую фишку в ZF?
Уже давно я пробовал трюк в callback + replace. Был доволен, но подход не слишком удобен.
Мысли мои пошли в следующую сторону.
Вот сам шаблон идеи.
PHP:
/* ... some code ...*/
<?php print '<'.'?'.'php'; ?> if (!$this->loggedIn()): <?php print '?'.'>' ?>
<?= $this->loginForm ?>
<?php print '<'.'?'.'php'; ?>
else:
$acl = "<?= $this->acl; ?>"; // Кешируем инфу о владельце новости и о доступе на редактирование
<?php print '?'.'>' ?>
/* ... print personal link ...*/
<?php print '<'.'?'.'php'; ?> endif; <?php print '?'.'>' ?>
/* ... some code ...*/
т.е. мы генерируем вид, который после рендеринга содержит код.
Перед запуском кеша страницы ловим все в буфер, и по окончании генерации страницы (или вызова ее из кеша) - исполняем содержимое буфера еще раз.
Таким образом, - реализуется т.н. "динамическое окно", или "дырка в кеше".
Страница в кеше - одна, а отображение различно, в зависимости от того, авторизован посетитель или нет, имеет он право редактировать страницу, или нет.
У этого способа есть один недостаток. Если мы недосмотрим, и предоставим пользователям возможность "внедрить php-code" - то получаем огромную дыру в безопасности.
Для подстраховки, можно сделать так:
PHP:
/* ... some code ...*/
<nocache key="shfkuigfbk78"> if (!$this->loggedIn()): </nocache key="shfkuigfbk78">
<?= $this->loginForm ?>
<nocache key="shfkuigfbk78">
else:
$acl = "<?= $this->acl; ?>"; // Кешируем инфу о владельце новости и о доступе на редактирование
</nocache key="shfkuigfbk78">
/* ... print personal link ...*/
<nocache key="shfkuigfbk78"> endif; </nocache key="shfkuigfbk78">
/* ... some code ...*/
Перед исполнением необходимо обезвредить таги php, например
PHP:
$str = str_replace(array('<'.'?', '?'.'>'), array('<?', '?>'), $str);
И сделать исполняемыми таги <nocache key="shfkuigfbk78">, т.е. заменить их на <?php и ?>
Получается двойная защита. Во-первых, маловероятно что xml-фильтр вводимых данных пропустит таг <nocache>.
Во вторых, даже если мы что-то недосмотрим, наш таг защищен секретным ключом, который злоумышленнику неизвестен.
Т.е., даже если он и сможет найти дыру, - то маловероятно, что он сможет разгадать секретную подпись.
Чтобы не вводить каждый раз вручную секретную строку, и сделать ее легкозаменяемой, - несложно написать хелпер nocache
И получится что-то типа такого:
PHP:
/* ... some code ...*/
<?= $this->nocache() ?> if (!$this->loggedIn()): <?= $this->nocache(true) ?>
<?= $this->loginForm ?>
<?= $this->nocache() ?>
else:
$acl = "<?= $this->acl; ?>"; // Кешируем инфу о владельце новости и о доступе на редактирование
<?= $this->nocache(true) ?>
/* ... print personal link ...*/
<?= $this->nocache() ?> endif; <?= $this->nocache(true) ?>
/* ... some code ...*/
В результате мы избавляемся от огромной избыточности кэша. Авторизованные юзеры просматривают страницы так же из кэша, хотя для них уже нет авторизационной формы, а вместо нее - персональное меню.
Решение до боли простое, достигнуто малой кровью, и Zend_Cache используется на полную мощность.