Кэширование в 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 сжатие ресурсов на сервере перед отправкой клиенту.

1927   0  

Comments

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