Я думаю, что в этом случае я бы использовал комбинацию кэширования действий и кэширования представлений. Я не буду вдаваться в капризы различных механизмов кэширования, а только основы для решения вашей проблемы.
Первое, что вам нужно сделать, это включить кеширование. В app/config/core.php
вам нужно внести пару изменений. Сначала закомментируйте строку Cache.disable
:
//Configure::write('Cache.disable', true);
Во-вторых, раскомментируйте строку Cache.check
:
Configure::write('Cache.check', true);
Наконец, вам нужно сделать CacheHelper
доступным для всех представлений, поэтому добавьте его к определению $helpers
в app/app_controller.php
:
class AppController extends Controller
{
var $helpers = array('Cache');
}
Далее мы настроим элемент view, который содержит меню вашей категории (выполнение представления до того, как будет выполнено управление, может показаться немного отсталым, но потерпите меня - это будет иметь смысл). Помещение меню в элемент представления делает его кэширование немного проще, чем попытка выборочно назначить части большего представления или макета как некэшированные с тегами <cake:no-cache></cake:no-cache>
.
Вот пример элемента представления, отображающий меню категорий в простом неупорядоченном списке (<ul>
):
<?php
$menuItems = $this->requestAction(array('controller'=>'categories','action'=>'menu'));
echo $html->nestedList( $menuItems, 'ul' );
?>
Возможно, в прошлом один или несколько человек говорили вам, что requestAction
является злом, поскольку оно инициирует целую новую отправку. Это правда. Вам следует избегать requestAction
, как чумы, , за исключением , когда вы используете этот тип кэширования представлений, и в этом случае это лучший способ.
Мы будем хранить этот новый элемент представления как app/views/elements/category_menu.ctp
. requestAction
вызывает действие menu
в CategoriesController
. Вот как выглядит CategoriesController
, а потом я буду разбираться с этим постепенно:
class CategoriesController extends AppController
{
var $cacheAction = array(
'menu/' => '1 day'
);
function menu()
{
return $this->Category->find('list', array(
'fields' => array('Category.id','Category.label'),
'order' => array('Category.order')
));
}
}
Что это делает:
- Определение элемента для
$cacheAction
говорит Cake, что он должен кэшировать результаты действия menu
в течение 1 дня.
- Метод
menu
возвращает одномерный массив категорий, используя Category.id
в качестве ключей и Category.label
в качестве значений.
Итак, давайте рассмотрим, что у нас так далеко. У нас есть элемент category_menu
, который запрашивает действие CategoriesController::menu
. Когда этот запрос получен, Cake проверит, кэширован ли результат этого действия и не истек ли он. Если кэшированный результат все еще действителен, Cake вернет его, не вызывая метод menu
, который мы определили. В противном случае Cake вызовет метод и кеширует результат. Элемент view затем отображает результат как nestedList.
Остается только использовать элемент представления в других представлениях. Вот простой пример app/views/layouts/default.ctp
:
<html>
[ snip... ]
<body>
<div class="category-menu">
<?php echo $this->element('category_menu', array('cache'=>'1 day')); ?>
</div>
<div class="content">
<p>Lorem ipsum sit dolor amet.</p>
</div>
</body
</html>
Мы используем знакомый View::element
для визуализации элемента представления category_menu
, который мы создали ранее, но мы также говорим Cake, что мы хотим, чтобы он визуализировал элемент представления один раз, затем кэшируем эту визуализированную версию и держим ее для месяц. Любые последующие запросы на этот элемент, пока не истечет месяц, или мы не очистим кеш, доставят предварительно обработанный элемент представления. Он даже не будет интерпретировать app/views/elements/category_menu.ctp
, а тем более вызывать requestAction
или попадать в базу данных.
Чтобы гарантировать, что изменения, внесенные вами в Category
записи модели, будут отражены немедленно, вы можете вызвать глобальную функцию clearCache()
в действиях создания / обновления. Одно замечание по поводу clearCache()
: это что-то вроде дробовика: не элегантно, но эффективно. clearCache()
уничтожает весь кеш, вместо выборочной очистки только необходимых представлений. Однако это простой подход, и, учитывая, что вы говорите об обновлении категорий ежемесячно, необходимость регенерировать кэш раз в месяц, вероятно, стоит меньших хлопот, связанных с более избирательным подходом.
Очень длинный ответ! НТН