Сайт на Yii2 работает быстро, пока данных мало. Но стоит базе подрасти, и страницы начинают грузиться вечность. Знакомо? Кеширование решает эту проблему, но многие боятся его настраивать. На самом деле всё проще, чем кажется. В этой статье разберём, как построить систему кеширования в Yii2, чтобы сайт летал, а вы спали спокойно.

Digital-студия WNDER

Зачем вообще нужно кеширование в Yii2

Представьте, что каждый раз, когда вы открываете страницу, сервер заново собирает все данные: лезет в базу, обрабатывает, формирует HTML. Это как каждый раз готовить борщ с нуля, даже если кастрюля уже стоит в холодильнике. Кеш — это та самая кастрюля: один раз приготовили, а потом только разогреваем. В Yii2 кеширование встроено на уровне фреймворка, и его можно использовать где угодно: для фрагментов страниц, данных, запросов к БД и даже для целых ответов.

Основные плюсы: снижение нагрузки на базу, ускорение отклика, экономия ресурсов сервера. Минусы: данные могут устаревать, нужна стратегия инвалидации. Но об этом позже.

Настраиваем компонент кеша

По умолчанию в Yii2 уже есть компонент cache, который использует файловый кеш. Для небольших проектов этого достаточно. Но если нагрузка растёт, лучше переключиться на Memcached или Redis. Настройка делается в конфиге приложения (обычно config/web.php или config/main.php).

Вот пример для файлового кеша (по умолчанию):

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

А так можно подключить Memcached:

'components' => [
    'cache' => [
        'class' => 'yii\caching\MemCache',
        'servers' => [
            [
                'host' => 'localhost',
                'port' => 11211,
                'weight' => 100,
            ],
        ],
    ],
],

Для Redis:

'components' => [
    'cache' => [
        'class' => 'yii\redis\Cache',
        'redis' => [
            'hostname' => 'localhost',
            'port' => 6379,
            'database' => 0,
        ],
    ],
],

После настройки можно обращаться к кешу через Yii::$app->cache.

Простые операции с кешем: get и set

Самые базовые методы — get() и set(). Выглядит это так:

$key = 'my_data_key';
$data = Yii::$app->cache->get($key);
if ($data === false) {
    // данных в кеше нет, вычисляем
    $data = heavyFunction();
    Yii::$app->cache->set($key, $data, 3600); // кешируем на час
}
return $data;

Здесь heavyFunction() — это какая-то тяжёлая операция (запрос к БД, вызов API). Если данных нет, выполняем и сохраняем. Время жизни указывается в секундах. Если не указать, кеш будет храниться вечно (пока не очистится вручную).

Также есть метод add() — он сохраняет значение, только если ключа ещё нет. Удобно для блокировок.

Кеширование фрагментов страницы

Часто нужно закешировать не данные, а готовый HTML-блок. Например, меню, список категорий или виджет. В Yii2 для этого есть виджет FragmentCache или обёртка $this->beginCache() / $this->endCache() в представлениях.

Пример:

<?php if ($this->beginCache('category_list', ['duration' => 3600])): ?>
    <ul>
        <?php foreach ($categories as $category): ?>
            <li><?= Html::encode($category->name) ?></li>
        <?php endforeach; ?>
    </ul>
    <?php $this->endCache(); ?>
<?php endif; ?>

Всё, что между beginCache и endCache, будет закешировано на час. При следующем запросе этот блок возьмётся из кеша, и PHP не будет выполняться. Это очень удобно для тяжёлых виджетов.

Зависимости кеша: как не показывать устаревшие данные

Главная проблема кеша — он устаревает. Например, вы закешировали список товаров, а цены изменились. Чтобы не показывать старые данные, используют зависимости. В Yii2 есть несколько типов зависимостей: DbDependency, FileDependency, ExpressionDependency и другие.

Самый частый случай — зависимость от запроса к БД. Пример:

use yii\caching\DbDependency;

$dependency = new DbDependency([
    'sql' => 'SELECT MAX(updated_at) FROM product',
]);
$key = 'product_list';
$data = Yii::$app->cache->get($key);
if ($data === false) {
    $data = Product::find()->all();
    Yii::$app->cache->set($key, $data, 3600, $dependency);
}
return $data;

Здесь кеш будет автоматически инвалидирован, если в таблице product появится запись с более новым updated_at. Удобно, правда? Главное — не забывать обновлять это поле при изменении данных.

Для фрагментов тоже можно указывать зависимости:

$this->beginCache('category_list', [
    'duration' => 3600,
    'dependency' => new DbDependency(['sql' => 'SELECT MAX(updated_at) FROM category']),
]);

Тегированный кеш: группируем и сбрасываем

Иногда нужно сбросить не весь кеш, а только связанные записи. Например, при обновлении статьи сбросить кеш всех страниц, где она выводится. Для этого используют теги. В Yii2 теги поддерживаются компонентом Cache через методы getOrSet с указанием тегов или через TagDependency.

Пример с TagDependency:

use yii\caching\TagDependency;

$key = 'article_'.$id;
$data = Yii::$app->cache->get($key);
if ($data === false) {
    $data = Article::findOne($id);
    TagDependency::invalidate(Yii::$app->cache, 'article_'.$id); // сбрасываем старые теги
    Yii::$app->cache->set($key, $data, 3600, new TagDependency(['tags' => ['article_'.$id]]));
}
return $data;

При обновлении статьи вы вызываете TagDependency::invalidate(Yii::$app->cache, 'article_'.$id), и все кеши с этим тегом становятся недействительными. Очень гибко.

Практические советы и лайфхаки

Правило: Всегда указывайте время жизни кеша (duration). Бессрочный кеш — это мина замедленного действия. Даже если используете зависимости, лучше подстраховаться.
  • Используйте префиксы для ключей. Например, 'user_'.$id, чтобы избежать коллизий.
  • Не кешируйте персонализированные данные (корзину, профиль) без привязки к пользователю.
  • Для отладки можно временно отключить кеш, установив компоненту cache в null или используя DummyCache.
  • Очищайте кеш при деплое, если меняется структура данных.

Сравнение типов кеша в Yii2:

Тип кеша Когда использовать Плюсы Минусы
FileCache Небольшие проекты, один сервер Простота, не требует установки Медленнее, чем память
MemCache Средние и крупные проекты Быстрый, распределённый Нужен отдельный сервис
Redis Высоконагруженные проекты Быстрый, поддерживает теги Сложнее в настройке

Что в итоге

Кеширование в Yii2 — это мощный инструмент, который может ускорить сайт в разы. Начните с простых фрагментов и данных, постепенно внедряйте зависимости и теги. Не бойтесь экспериментировать: всегда можно отключить кеш и проверить, как работает без него. Главное — не забывайте сбрасывать кеш при изменении данных, иначе пользователи увидят устаревшую информацию.

Надеюсь, статья была полезной. Удачи в оптимизации!

Студия WNDER