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

Что такое кеширование и зачем оно нужно в Yii2

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

Представьте, что вы печёте пирожки. Если каждый раз замешивать тесто заново — это долго. Но если вы приготовили тесто заранее и храните его в холодильнике, то просто достаёте и печёте. Кеш — это тот самый холодильник.

Yii2 поддерживает много видов кеширования: кеш страниц, фрагментов, данных, запросов и даже HTTP-кеш. Встроенные компоненты упрощают настройку до минимума.

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

Первый шаг — включить кеширование в конфигурации приложения. В файле config/web.php добавляем компонент cache. Yii2 поддерживает несколько драйверов: файловый, Memcached, Redis, APC и другие. Для начала подойдёт файловый кеш — он не требует установки дополнительного ПО.

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

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

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

Не забудьте установить расширение yiisoft/yii2-redis через Composer. После настройки кеш готов к работе.

Кеширование данных: простые примеры

Самый распространённый способ — кеширование результатов запросов к базе данных. Допустим, у вас есть список категорий, который редко меняется. Вместо того чтобы каждый раз делать SQL-запрос, сохраняем результат в кеш.

$categories = Yii::$app->cache->get('categories');
if ($categories === false) {
    $categories = Category::find()->all();
    Yii::$app->cache->set('categories', $categories, 3600); // храним 1 час
}

Здесь get пытается достать данные из кеша. Если их нет, выполняем запрос и сохраняем результат на час. Третий параметр — время жизни в секундах. Можно не указывать, тогда данные будут храниться вечно, пока их не удалят вручную.

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

$key = 'user_profile_' . $userId;
$profile = Yii::$app->cache->get($key);
if ($profile === false) {
    $profile = User::findOne($userId)->profile;
    $dependency = new \yii\caching\DbDependency([
        'sql' => 'SELECT MAX(updated_at) FROM user_profile WHERE user_id = :id',
        'params' => [':id' => $userId],
    ]);
    Yii::$app->cache->set($key, $profile, 3600, $dependency);
}

Зависимость проверяет, изменилась ли запись в базе. Если да — кеш сбрасывается автоматически.

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

Yii2 позволяет кешировать не только данные, но и части HTML-кода. Это полезно для блоков, которые рендерятся долго, например, меню или виджеты. Используйте виджет FragmentCache:

use yii\widgets\FragmentCache;

<?php FragmentCache::begin([
    'id' => 'top-menu',
    'duration' => 3600,
    'dependency' => [
        'class' => 'yii\caching\DbDependency',
        'sql' => 'SELECT MAX(updated_at) FROM menu',
    ],
]); ?>

<!-- ваш HTML для меню -->
<ul>
    <li><a href="/">Главная</a></li>
    <li><a href="/about">О нас</a></li>
</ul>

<?php FragmentCache::end(); ?>

Если нужно кешировать всю страницу целиком, используйте фильтр PageCache в контроллере:

use yii\filters\PageCache;

public function behaviors()
{
    return [
        [
            'class' => PageCache::class,
            'only' => ['index'],
            'duration' => 60,
            'variations' => [
                Yii::$app->language,
                Yii::$app->request->get('page'),
            ],
        ],
    ];
}

Этот фильтр кеширует ответ для действия index на 60 секунд. Параметр variations учитывает язык и номер страницы, чтобы кеш был уникальным для разных вариантов.

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

Сравнение драйверов кеширования

Выбор драйвера влияет на скорость и надёжность. Вот таблица популярных вариантов:

ДрайверСкоростьУстановкаОсобенности
FileCacheНизкаяНе требуетсяПодходит для разработки, медленнее на больших объёмах
MemcachedВысокаяТребует сервер MemcachedХранит в ОЗУ, распределённый
RedisОчень высокаяТребует сервер RedisПоддерживает сложные структуры, очереди
APCВысокаяPHP-расширениеУстарел, используйте APCu

Для продакшена рекомендую Redis — он быстрый, надёжный и легко масштабируется. Memcached тоже хорош, но не поддерживает постоянное хранение (кеш сбрасывается при перезагрузке).

Лайфхаки и частые ошибки

  • Не забывайте про инвалидацию кеша. Если данные изменились, кеш должен обновиться. Используйте зависимости или вручную сбрасывайте ключи после записи в базу.
  • Не кешируйте слишком много. Большой кеш замедляет поиск. Оптимальный размер — до нескольких тысяч ключей на один сервер.
  • Используйте теги кеша (если драйвер поддерживает). В Yii2 это возможно через TagDependency — сбрасывайте сразу группу ключей.
$cache = Yii::$app->cache;
$cache->set('post_123', $data, 3600, new \yii\caching\TagDependency(['tags' => 'posts']));
// Позже сбросить все кеши с тегом posts:
TagDependency::invalidate($cache, 'posts');
Лайфхак: Для отладки кеша используйте расширение yii-debug-toolbar. Оно покажет, сколько запросов было взято из кеша, а сколько выполнено в базе. Это поможет найти узкие места.

Итоги

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

Студия WNDER