Кеширование в Yii с помощью тегов

в 9:23, , рубрики: php, yii, yii framework, метки: , ,

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

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js