Когда ваше 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 для продакшена. Кешируйте данные, фрагменты и страницы, но не забывайте про инвалидацию. Используйте зависимости и теги, чтобы кеш всегда был актуальным. Следуя этим советам, вы сократите время загрузки страниц в несколько раз, а пользователи скажут спасибо.


