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

Digital-студия WNDER

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

Кеширование — это сохранение готового результата работы скрипта, чтобы не выполнять её повторно. Представьте, что вы печёте пирог по сложному рецепту каждый раз, когда к вам приходят гости. Это долго и утомительно. Вместо этого можно испечь несколько пирогов заранее и подавать их гостям мгновенно. Так и с сайтом: вместо повторной генерации 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 минут.

Лайфхак: Всегда устанавливайте разумное время жизни кеша. Слишком маленькое — не даст эффекта, слишком большое — может показывать устаревшие данные. Для большинства страниц оптимально 60–300 секунд.

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 Заголовки, кеш браузера Все страницы, особенно для гостей Зависит от настроек

Распространённые ошибки и как их избежать

При работе с кешированием легко наступить на грабли. Вот частые ошибки:

  • Кеширование динамических данных. Не кешируйте страницы с корзиной, личным кабинетом или другими пользовательскими данными. Используйте фрагментное кеширование.
  • Забыли про вариации. Если сайт мультиязычный или имеет разные версии для разных ролей, обязательно добавляйте вариации.
  • Слишком долгий срок жизни. Это приводит к устареванию информации. Лучше уменьшить время и добавить признак актуальности.
  • Игнорирование сброса кеша. При обновлении данных не забывайте сбрасывать кеш вручную или автоматически.
Правило: Всегда продумывайте стратегию инвалидации кеша. Используйте зависимости — например, теги или версии. В Yii2 есть механизм зависимостей, который автоматически сбрасывает кеш при изменении данных.

Пример использования зависимости:

$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. Применяйте на практике и наслаждайтесь быстрым откликом вашего приложения.

Студия WNDER