Yii позволяет кешировать данные в виде массива возвращаемые прямиком из базы данных.
А у системы кеширования есть разные зависимости. Вот только ни одна из этих зависимостей не позволяет автоматически отслеживать изменения в таблице без обращения к ней же (имею ввиду CDbCacheDependency), что в нагруженных системах бессмысленно.
Для подобных вещей придумали так называемое тегирование. Т.е. создается какой-то тег, который сохраняется со всеми кешами связанными с данной таблицей. И как только он меняется, все связанные кеши должны перезагрузиться. Как оказалось в Yii это делается очень просто.
Стоит упомянуть, что для большего комфорта используется Active Record.
Делается это так. Создаем новую зависимость и сохраняем ее, к примеру в components:
/**
* CTagCacheDependency class.
*
* CTagCacheDependency represents a dependency based on a autoincrement(timestamp) of tags
*
* @author Roman <astronin@gmail.com>
* @since 1.0
*/
class CTagCacheDependency extends CCacheDependency
{
/**
* @var autoincrement(timestamp) param is used to
* check if the dependency has been changed.
*/
public $tag;
/**
* Cache component, by default used - cache
* @var CCache
*/
public $cache;
/**
* Constructor.
* @param string $tag value of the tag for module
*/
public function __construct($tag=null, $cache=null)
{
$this->tag = $tag;
$this->cache = ($cache)?$cache:Yii::app()->cache;
}
/**
* Generates the data needed to determine if dependency has been changed.
* This method returns the integer(timestamp).
* @return mixed the data needed to determine if dependency has been changed.
*/
protected function generateDependentData()
{
if($this->tag!==null)
{
$t = $this->cache->get($this->tag);
if ($t === false) {
$t = mikrotime();
$this->cache->set($this->tag, $t);
}
return $t;
}
}
}
В модели указываем, когда мы будем использовать новую зависимость. Поскольку мы хотим это сделать для всей модели добавляем код в функцию beforeFind:
protected function beforeFind() {
$this->cache(30, new CTagCacheDependency(get_class($this)));
parent::beforeFind();
}
Ну или где хотим, главное тут — "$this->cache(30, new CTagCacheDependency(get_class($this)));"
- 30 — время хранения кеша, но лучше вынести это значение в переменную
- CTagCacheDependency — класс нашей новой зависимости
- get_class($this) — имя тега — имя модели
В качестве тега у нас выступает просто название класса, модели, связанной с определенной таблицей.
Ну и когда мы удаляем или сохраняем что-то, пишем в нужных местах(в функциях afterDelete, afterSave):
Yii::app()->cache->set(get_class($this), mikrotime(), 0);
- 0 — бесконечное хранение
- get_class($this) — имя тега — имя модели
- mikrotime() — новое значение тега
Этим самым мы обновляем тег связанный с данной моделью, а соответственно и с таблицей. Теперь, когда тег обновится в следствии обновления таблицы, все кеши с зависимостью от этого тега должны будут обновиться.
Используется кеш по-умолчанию — компонент: cache. Но можно указать другой свой.
Используемая литература:
Автор: AstRonin