Каждый разработчик сталкивался с ситуацией, когда сайт начинает тормозить под нагрузкой. Особенно это заметно на проектах с большим количеством запросов к базе данных или сложными вычислениями. В Yii2 есть мощный инструмент для решения этой проблемы — кеширование страниц. В этой статье я расскажу, как правильно его настроить, чтобы ваш сайт летал, а не ползал.
Что такое кеширование страниц и зачем оно нужно
Кеширование — это сохранение готового результата работы скрипта, чтобы не выполнять её повторно. Представьте, что вы печёте пирог по сложному рецепту каждый раз, когда к вам приходят гости. Это долго и утомительно. Вместо этого можно испечь несколько пирогов заранее и подавать их гостям мгновенно. Так и с сайтом: вместо повторной генерации HTML-кода для каждого посетителя мы сохраняем его после первого запроса и отдаём копию.
В Yii2 кеширование страниц особенно полезно для страниц, которые редко меняются и требуют много ресурсов: каталоги, списки новостей, главные страницы. Оно снижает нагрузку на сервер и базу данных, ускоряет ответ пользователю.
Основные виды кеширования в Yii2
В Yii2 есть несколько уровней кеширования, и каждый из них решает свою задачу:
- Кеширование данных — сохранение результатов запросов к БД или вычислений.
- Кеширование фрагментов — кеширование части страницы, например, меню или боковой панели.
- Кеширование страниц — полное сохранение HTML-вывода страницы.
- HTTP-кеширование — использование заголовков для кеширования на стороне браузера или прокси-сервера.
В этой статье мы сосредоточимся на кешировании страниц, так как оно даёт наибольший прирост производительности.
Настройка компонента кеша в Yii2
Прежде чем использовать кеширование, нужно настроить компонент cache в конфигурации приложения. В Yii2 доступны разные хранилища: файлы, memcached, redis, APC и другие. Для большинства проектов достаточно файлового кеша, но для высоконагруженных систем лучше использовать Redis или Memcached.
Вот пример настройки файлового кеша в файле config/web.php:
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
'cachePath' => '@runtime/cache',
],
],
Если вы хотите использовать Redis, настройка будет выглядеть так:
'components' => [
'cache' => [
'class' => 'yii\redis\Cache',
'redis' => [
'hostname' => 'localhost',
'port' => 6379,
'database' => 0,
],
],
],
После настройки компонента вы можете использовать его в любом месте приложения через Yii::$app->cache.
Кеширование страниц с помощью поведений
В Yii2 есть специальное поведение PageCache, которое позволяет кешировать вывод целого действия контроллера. Это очень удобно: вы просто подключаете поведение к контроллеру и указываете параметры кеша.
Рассмотрим пример. Допустим, у нас есть контроллер SiteController с действием actionIndex, которое выводит главную страницу. Чтобы закешировать эту страницу на 60 секунд, добавим поведение:
use yii\web\Controller;
use yii\filters\PageCache;
class SiteController extends Controller
{
public function behaviors()
{
return [
[
'class' => PageCache::className(),
'only' => ['index'],
'duration' => 60,
'variations' => [
\Yii::$app->language,
],
],
];
}
public function actionIndex()
{
return $this->render('index');
}
}
Что здесь происходит? Мы говорим, что для действия index нужно сохранять результат в кеш на 60 секунд. Параметр variations позволяет создавать разные копии кеша в зависимости от языка пользователя. Это важно для мультиязычных сайтов.
Также можно кешировать страницы с параметрами. Например, если у вас есть страница списка товаров с пагинацией, вы можете включить номер страницы в вариации:
'variations' => [
\Yii::$app->request->get('page', 1),
],
Таким образом, каждая страница пагинации будет кешироваться отдельно.
Кеширование фрагментов и данных
Иногда кешировать всю страницу нельзя — например, если на ней есть корзина или личный кабинет пользователя. В таких случаях можно кешировать отдельные фрагменты с помощью виджета FragmentCache.
Пример использования в представлении:
<?php if ($this->beginCache('menu', ['duration' => 3600])): ?>
<!-- Здесь выводим меню, которое редко меняется -->
<?= \app\widgets\Menu::widget() ?>
<?php $this->endCache(); endif; ?>
Такой подход позволяет кешировать только тяжёлые элементы, оставляя остальную часть страницы динамической.
Также можно кешировать результаты запросов к базе данных. Например:
$data = Yii::$app->cache->getOrSet('top_products', function () {
return Product::find()->where(['status' => 1])->limit(10)->all();
}, 300);
Здесь мы получаем список товаров из кеша, а если его нет — выполняем запрос и сохраняем результат на 5 минут.
HTTP-кеширование и заголовки
Помимо серверного кеширования, можно использовать HTTP-кеширование, чтобы браузер пользователя или прокси-сервер хранили копию страницы. Это уменьшает количество запросов к серверу.
В Yii2 можно установить заголовки через ответ:
public function actionIndex()
{
$response = Yii::$app->response;
$response->headers->set('Cache-Control', 'public, max-age=3600');
$response->headers->set('ETag', 'abc123');
return $this->render('index');
}
Но удобнее использовать встроенное поведение HttpCache:
use yii\filters\HttpCache;
public function behaviors()
{
return [
[
'class' => HttpCache::className(),
'only' => ['index'],
'lastModified' => function ($action, $params) {
return time() - 3600; // время последнего изменения
},
'etagSeed' => function ($action, $params) {
return 'my-unique-seed';
},
],
];
}
Этот подход особенно полезен для статических страниц, которые редко меняются.
Таблица сравнения видов кеширования
| Вид кеширования | Что кешируется | Когда использовать | Примерное время жизни |
|---|---|---|---|
| Данные | Результаты запросов, вычислений | Тяжёлые запросы, повторяющиеся данные | 60–600 сек |
| Фрагменты | Части представления | Меню, блоки, виджеты | 300–3600 сек |
| Страницы | Полный HTML-вывод | Статические или редко меняющиеся страницы | 30–300 сек |
| HTTP | Заголовки, кеш браузера | Все страницы, особенно для гостей | Зависит от настроек |
Распространённые ошибки и как их избежать
При работе с кешированием легко наступить на грабли. Вот частые ошибки:
- Кеширование динамических данных. Не кешируйте страницы с корзиной, личным кабинетом или другими пользовательскими данными. Используйте фрагментное кеширование.
- Забыли про вариации. Если сайт мультиязычный или имеет разные версии для разных ролей, обязательно добавляйте вариации.
- Слишком долгий срок жизни. Это приводит к устареванию информации. Лучше уменьшить время и добавить признак актуальности.
- Игнорирование сброса кеша. При обновлении данных не забывайте сбрасывать кеш вручную или автоматически.
Пример использования зависимости:
$dependency = new \yii\caching\DbDependency([
'sql' => 'SELECT MAX(updated_at) FROM product',
]);
$data = Yii::$app->cache->getOrSet('products', function () {
return Product::find()->all();
}, 3600, $dependency);
Теперь кеш будет сброшен автоматически, как только изменится максимальная дата обновления в таблице product.
Итоги
Кеширование страниц в Yii2 — это простой и эффективный способ ускорить ваш сайт. Начните с настройки компонента cache, затем добавьте поведение PageCache к наиболее тяжёлым страницам. Если страницы содержат динамические элементы, используйте фрагментное кеширование. Не забывайте про HTTP-кеширование для статики.
Главное — не переусердствовать. Кеширование не должно мешать актуальности данных. Тестируйте производительность до и после внедрения, чтобы убедиться в положительном эффекте.
Надеюсь, эта статья помогла вам разобраться в кешировании Yii2. Применяйте на практике и наслаждайтесь быстрым откликом вашего приложения.



