Кэширование в YII2



Самый быстрый способ повысить производительность, улучшить скорость WEB-приложений - это однозначно кэширование. Основной механизм кэширование - это отсутствие генерации данных кодом php и постоянное обращение к базе данных. Кэширование позволяет сохранить данные в установленном месте еще при первоначальном запросе и потом уже считывать их. Разработчик устанавливает место и время хранения кэша.

Далее мы описали несколько вариантов работы с кэшем, которые вы сможете применить на практике.

Общий кэш для backend и frontend.

Как принято изначально кэш в Yii2 (Advanced) сохраняется в виде файла в соответствующие папки:

  • backend\runtime\cache;
  • frontend\runtime\cache.

Из изложенного выше понятно, что у frontend и backend собственные папки кэша и из админки удалить кэш frontenda не возможно. С помощью команды:

Yii::$app->cache

можно увидеть место кэширования для текущего приложения.

Для кэширования данных из другого приложения ((например из frontend удалить кэш backenda) необходимо указать общее хранилище в конфигурации для этих приложений.

Например, кэширование frontend и backend происходит в одном месте делаем следующим образом:

↓↓↓↓↓↓↓Ищем файл ↓↓↓↓↓↓↓↓

mon\config\main.php

Дописываем строку с "cachePath":

'components' => [
 'cache' => [
 'class' => 'yii\caching\FileCache',
 'cachePath' => '@frontend/runtime/cache',
 ],

Миграция. База данных

Есть различные места для хранения кэша. Сейчас мы рассмотрим - базу данных.

↓↓↓↓↓↓↓Ищем файл ↓↓↓↓↓↓↓↓

mon\config\main.php

Указываем класс работающий с БД:

'components' => [
 'cache' => [
 'class' => 'yii\caching\DbCache',
 ],

Для использования данного кэша, необходимо создать таблицу. Если уже используете миграцию при работе с БД, или знаете как она запускается, то вам легче будет создать данную таблицу с помощью кода ниже:

public function safeUp()
{
 $tableOptions = null;
 if ($this->db->driverName === 'mysql') {
 $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_general_ci ENGINE=InnoDB';
 }
 $this->createTable('{{%cache}}', [
 'id' => $this->primaryKey(),
 'expire' => $this->integer(11),
 'data' => $this->text(),
 ], $tableOptions);
}
public function safeDown()
{
 $this->dropTable('{{%cache}}');
}

Удаление кэша автоматическое при обновлении записи в базе данных.

Когда вы вносите изменения в БД (например, редактируете пост в админке), данные в кэше теряют свою актуальность.

Зависимость (dependency) не дает гарантий сохранения данных, при изменении их, но не добавлении например. В данной ситуации к модели, в соответствии с определенной таблицей задействованной в кэшировании (виджет), необходимо подключить поведение с событиями для ActiveRecord:

EVENT_AFTER_INSERT

EVENT_AFTER_UPDATE

EVENT_AFTER_DELETE

при этих событиях будет удален нужных кэш. Для удаления кэша frontenda из админки, применяется общее хранилище кэша для backend и frontend (выше описано как).

↓↓↓↓↓↓↓↓В папке↓↓↓↓↓↓↓↓

common\components\behaviors

↓↓↓↓↓↓↓↓необходимо создать файл↓↓↓↓↓↓↓↓ 

CachedBehavior.php

<?php
namespace common\components\behaviors;
use Yii;
use yii\base\Behavior;
use yii\db\ActiveRecord;
class CachedBehavior extends Behavior
{
 //id кэша - название в виде массива
 public $cache_id;
 public function events()
 {
 return [
 ActiveRecord::EVENT_AFTER_INSERT => 'deleteCache',
 ActiveRecord::EVENT_AFTER_UPDATE => 'deleteCache',
 ActiveRecord::EVENT_AFTER_DELETE => 'deleteCache',
 ];
 }
 public function deleteCache()
 {
 //Удаление массива кэшированных элементов (виджеты, модели...)
 Foreach ($this->cache_id as $id){
 Yii::$app->cache->delete($id);
 }
 }
}

Обновляем данные, которые хранятся в кэше, подключение в модели:

public function behaviors()
{
 parent::behaviors();
 return [
 'CachedBehavior' => [
 'class' => \common\components\behaviors\CachedBehavior::className(),
 'cache_id' => ['CloudWidget'],
 ],
 ];
}

Элемент массива 'cache_id' = id кэша (необходимо его удалить), в указанном случае - 'CloudWidget'. Можно передавать несколько значений.

Как автоматически удалить кэш при осуществлении действий контроллера.

При выполнении действий контроллера, которые меняют актуальность файлов в кэше, необходимо настроить автоматическое их удаление. Например, удаляете пост (actionDelete()) при этом хотите файл карты сайта для поисковых служб по причине его не актуальности. Как это сделать указано в коде выше, событие - ActiveRecord. Эта модель с привязкой поведения используется и в frontend выводя те же посты, где привязка такого поведения не нужна. Исходя из этого используем вариант, который базируется на событии EVENT_BEFORE_ACTION контроллера, который нужен в backend.

Для удаления из админки кэша frontenda, используйте общее хранилище кэша для backend и frontend (об этом писали выше).

↓↓↓↓↓↓↓↓ Вносим класс поведения в↓↓↓↓↓↓↓↓ 

backend\controllers\PostController.php

public function behaviors()
 {
 return [
 //Класс удаление кэша при выполнении указанных действий
 [
 'class' => '\common\components\behaviors\DelcacheBehavior',
 'cache_id' => ['CloudWidget'],
 'actions' => ['create', 'update', 'delete'],
 ],
 ];

↓↓↓↓↓↓↓↓ Файл↓↓↓↓↓↓↓↓ 

common\components\behaviors\DelcacheBehavior.php

<?php
/*
 * Класс удаляющий кэш по переданным в массиве $cache_id названиям (id) кэша
 * перед выполнением указанных действий контроллера в массиве $actions
 */
namespace common\components\behaviors;
use Yii;
use yii\base\Behavior;
use yii\web\Controller;
class DelcacheBehavior extends Behavior {
 public $cache_id; //id кэша (названия в виде массива)
 public $actions; //для каких действий контроллера
 public function events()
 {
 return [
 Controller::EVENT_BEFORE_ACTION => 'deleteCache',
 ];
 }
 public function deleteCache()
 {
 $action_name = $this->owner->action->id; //название текущего действия
 if(array_search($action_name, $this->actions)=== FALSE) return;
 //Удаление массива кэшированных элементов (виджеты, модели...)
 Foreach ($this->cache_id as $id){
 Yii::$app->cache->delete($id);
 }
 }
}

CloudWidget (файл кэша) удален.

Рассмотрим кэширование на примерах.

Фрагменты страниц и кэширование.

Область применения - вывод виджетов, при необходимости закэшировать частично страницу

<?php
 //кеш на час
 if ($this->beginCache('TagListWidget', ['duration' => 3600])) {
 echo common\widgets\TagListWidget::widget();
 $this->endCache(); }
?>
<?php
 //Зависимость кеша от кол-ва записей
 $dependency = [
 'class' => 'yii\caching\DbDependency',
 'sql' => 'SELECT COUNT(*) FROM {{%comments}}',
 ];
 if ($this->beginCache('LcommentsWidget', ['dependency' => $dependency])) {
 echo common\widgets\LcommentsWidget::widget();
 $this->endCache();
 }
?>

Кэширование данных (значения переменной).

$cache = Yii::$app->cache;
//Кешируем массив $arr_tags
if (!$arr_tags = $cache->get('TaglistWidget_init')){
 //Получаем данные из таблицы (модель TagPost)
 $tag_post = TagPost::find()
 ->select('tag_id')
 ->where(['not',['post_id' => null]])
 ->all();
 $arr_tags = array();
 foreach($tag_post as $tag_id){
 $arr_tags[] = $tag_id->tag_id;
 }
 //Устанавливаем зависимость кеша от кол-ва записей в таблице
 $dependency = new \yii\caching\DbDependency(['sql' => 'SELECT COUNT(*) FROM {{%tag_post}}']);
 $cache->set('TaglistWidget_init', $arr_tags, null, $dependency);

Кэширование запросов к БД.

Может быть применимо как для DAO, так и для ActiveRecord

$result = $db->cache(function ($db) {
 // Результат SQL запроса будет возвращен из кэша если
 // кэширование запросов включено и результат запроса присутствует в кэше
 return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();
});

Помните! Существует еще клиентское HTTP-кэширование и Gzip сжатие ресурсов на сервере перед отправкой клиенту.

491   0  
    Ничего не найдено.

Добавить ответ:
Отменить.