Кеширование
Кеш — временное хранилище готовых результатов. Если список свежих статей с авторами собирается долго, его вычисляют один раз, кладут в кеш и следующие несколько минут отдают оттуда, не обращаясь к базе.
Где настраивается кеш
Кеш — компонент cache. Он уже описан в config/web.php:
// config/web.php
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
],FileCache хранит данные в файлах в папке runtime/cache, ничего дополнительно устанавливать не нужно.
Запись и чтение
// controllers/PostController.php
public function actionLatest(): string
{
$posts = Yii::$app->cache->getOrSet('latest-posts', function () {
return Post::find()->orderBy(['created_at' => SORT_DESC])->limit(5)->all();
}, 600);
return $this->render('index', ['posts' => $posts]);
}getOrSet() ищет в кеше значение с ключом latest-posts. Если его нет, выполняет функцию, сохраняет результат на 600 секунд и возвращает его. Первое открытие страницы выполнит запрос к базе, следующие десять минут — нет; это видно по числу запросов в панели отладки.
Методы кеша
| Вызов | Что делает |
|---|---|
$cache->set('key', $value, 600) | Сохраняет значение на 600 секунд |
$cache->get('key') | Возвращает значение или false, если его нет |
$cache->getOrSet('key', $callable, 600) | Читает, а при отсутствии вычисляет и сохраняет |
$cache->delete('key') | Удаляет значение |
$cache->flush() | Очищает весь кеш |
Сброс при изменении
Устаревший кеш удаляют, когда данные меняются. Удобное место — метод модели, который Yii вызывает после каждого сохранения:
// models/Post.php
public function afterSave($insert, $changedAttributes): void
{
parent::afterSave($insert, $changedAttributes);
Yii::$app->cache->delete('latest-posts');
}После создания или изменения статьи список свежих статей пересчитается при следующем открытии страницы.
Кеш запросов
Результат отдельного запроса к базе кешируют методом cache():
$posts = Post::find()->where(['status' => 1])->cache(60)->all();В течение минуты одинаковый запрос будет возвращать сохранённые строки.
Кеш части шаблона
Готовую разметку блока тоже можно сохранить:
<?php
// views/layouts/main.php
?>
<?php if ($this->beginCache('sidebar', ['duration' => 300])): ?>
<aside>
<!-- тяжёлый блок: облако тегов, последние комментарии -->
</aside>
<?php $this->endCache(); ?>
<?php endif; ?>Первый раз блок выполняется и сохраняется, следующие пять минут Yii подставляет готовую разметку и код внутри не выполняет.
Очистка из консоли
php yii cache/flush-allКоманда очищает все компоненты кеша, описанные в config/console.php.
Другие хранилища
На нагруженных сайтах файлы заменяют хранилищем в памяти — меняется только класс компонента, код остаётся прежним: yii\caching\MemCache для Memcached, yii\redis\Cache из пакета yiisoft/yii2-redis для Redis.
Частая ошибка
Метод get() возвращает false, когда значения нет. Если в кеш положить само значение false или проверять результат через if (!$value), пустой массив и ноль будут приняты за промах, и кеш не сработает. Сравнивайте строго: if ($value === false) — или пользуйтесь getOrSet().