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

Digital-студия WNDER

Зачем вообще кешировать данные в Yii2

Представь, что ты каждый раз, когда хочешь узнать время, идёшь в другой город за часами. Смешно, правда? А ведь именно так работает приложение без кеша: каждый запрос к странице заставляет базу данных снова и снова выполнять одни и те же тяжёлые запросы. Yii2 предоставляет мощный компонент cache, который умеет хранить данные в файлах, памяти или Redis. Но просто включить его недостаточно — нужно правильно организовать слои кеширования.

Основная идея: мы перехватываем результаты дорогих операций (запросы к БД, вызовы API, рендеринг блоков) и сохраняем их на время. При следующем запросе отдаём готовое, не напрягая сервер.

Настройка компонента cache

В Yii2 кеш настраивается в конфиге приложения. По умолчанию используется файловый кеш, но для продакшена лучше взять что-то пошустрее, например, Memcached или Redis. Вот пример конфигурации для Redis:

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

Если Redis нет, можно использовать yii\caching\FileCache или yii\caching\DbCache. Главное — не оставлять всё на самотёк.

Правило: Всегда задавайте уникальный keyPrefix для каждого проекта, чтобы кеш разных приложений не смешивался.

Три уровня кеширования: данные, фрагменты, страницы

В Yii2 можно кешировать на разных уровнях. Выбирайте под задачу:

Уровень Что кешируем Инструмент Yii2
Данные Результаты запросов, вычисления Yii::$app->cache->get()/set()
Фрагменты HTML-блоки, виджеты $this->beginCache()/endCache()
Страницы Целые ответы yii\filters\PageCache

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

$orders = Yii::$app->cache->get('all_orders');
if ($orders === false) {
    $orders = Order::find()->with('user')->all();
    Yii::$app->cache->set('all_orders', $orders, 3600); // кеш на час
}
return $orders;

Этот код проверяет, есть ли данные в кеше. Если нет — делает запрос и сохраняет результат на час. Всё просто.

Кеширование фрагментов: когда страница разная, а блок — нет

Иногда страница зависит от пользователя, но какой-то блок (например, список популярных товаров) одинаков для всех. Тут пригодится кеширование фрагментов. Внутри представления:

beginCache('popular_products', ['duration' => 3600])): ?>
    
endCache(); endif; ?>

Yii2 сам сгенерирует ключ на основе имени блока и параметров. Если нужно учесть язык или категорию, добавьте variations:

$this->beginCache('popular_products', [
    'duration' => 3600,
    'variations' => [Yii::$app->language, $categoryId],
]);
Лайфхак: Используйте dependency в кеше фрагментов, чтобы автоматически сбрасывать кеш при изменении данных. Например, DbDependency с SQL-запросом.

Кеширование страниц целиком: PageCache

Если страница полностью статична для всех (или почти всех), можно кешировать весь ответ. В контроллере добавляем фильтр:

public function behaviors()
{
    return [
        'pageCache' => [
            'class' => 'yii\filters\PageCache',
            'only' => ['index', 'view'],
            'duration' => 7200,
            'dependency' => [
                'class' => 'yii\caching\DbDependency',
                'sql' => 'SELECT MAX(updated_at) FROM product',
            ],
        ],
    ];
}

Теперь страницы index и view будут отдаваться из кеша 2 часа. Но как только в таблице product обновится запись, кеш сбросится автоматически. Удобно!

Продвинутые техники: теги и зависимости

Чтобы не сбрасывать весь кеш при малейшем изменении, используйте теги. Например, помечаем кеш тегом products:

Yii::$app->cache->set('product_list', $data, 3600, new TagDependency(['tags' => 'products']));

А при обновлении любого товара вызываем:

TagDependency::invalidate(Yii::$app->cache, 'products');

Это гибче, чем сбрасывать всё подряд. Также можно комбинировать зависимости: ChainedDependency позволяет объединить несколько условий.

Вот таблица с основными зависимостями Yii2:

Класс Когда использовать
DbDependency Зависимость от результата SQL-запроса
FileDependency Зависимость от времени изменения файла
TagDependency Групповая инвалидация по тегам
ChainedDependency Комбинация нескольких зависимостей

Что в итоге

Построение системы кеширования в Yii2 — это не магия, а последовательность шагов. Настройте компонент cache, выберите уровни (данные, фрагменты, страницы), добавьте зависимости и теги для умного сброса. Начните с малого: закешируйте один тяжёлый запрос, замерьте скорость. Потом расширяйте. И помните: кеш — это компромисс между скоростью и актуальностью. Не кешируйте то, что меняется каждую секунду, если это критично.

Внедрив описанные приёмы, вы удивитесь, насколько быстрее станет ваш проект на Yii2. База данных скажет спасибо, а пользователи — тем более.

Студия WNDER