Как кешировать страницы и фрагменты - vorst.ru

Кеширование


ускорение (оптимизация) работы сайта с помощью кеширования

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

Кеширование

ускорение (оптимизация) работы сайта с помощью кеширования

Содержание конкретной страницы, как правило, требует предварительной подготовки. Например, в посте присутствует сразу текст на русском и на английском языке, как было предложено ранее. В этом случае нужна предварительная обработка, чтобы на экране отображался только текст на текущем языке.

Если текст поста меняется редко, желательно выполнять работу по подготовке страниц в "первый" просмотр и затем выводить уже готовые страницы.


В Yii2 по умолчанию предусмотрено использование механизма ускорения вывода контента. В конфигурационном файле common/config/main.php из коробки можно увидеть следующие строчки,

'components' => [
    'cache' => [
        'class' => 'yii\caching\FileCache',
    ],

которые позволяют записывать подготовленные данные в стандартный файл. Когда данные понадобятся снова, их можно будет найти по ключу.

Но возможность не обеспечивает подготовку контента автоматически. Это нужно делать самостоятельно.

В блоге можно заранее подготовить страницы для дальнейшего быстрого вывода: список постов - post/index и конкретный пост - post/view.

Page Caching

Начнем с вывода конкретного поста или с действия view контроллера frontend\controllers\PostController.php

public function actionView($id)
{
    $cache = Yii::$app->cache;
    $key = "view-" . Yii::$app->language . "-" . $id;
    if($view = $cache->get($key))
        return $view;
    $dependency = new \yii\caching\DbDependency([
        'sql' => 'SELECT updated_at FROM post WHERE id='. $id,
    ]);
    $model = $this->loadModel($id);
    $view = $this->render('view', [
        'model' => $model,
    ]);
    $cache->set($key, $view, 0, $dependency);
    return $view;
}

Сначала проверим, есть ли уже такой ключ в хранилище. Если да, то выводим ранее подготовленную страницу. Если нет, то готовим страницу, сохраняем и выводим. Все просто.

Готовые страницы могут служить длительное время, но все меняется. Очевидно страница, сохраненная в хранилище, устареет при внесении изменений в пост.

Если страница устарела, метод get вернет false. При сохранении страницы методом set была передана зависимость - dependency, позволяющая определить факт того, что страница устарела. В примере сохраняется дата последней модификации поста. Если дата изменилась, get вернет false, страница будет переверстана и сохранена под тем же ключом.

Для действия index алгоритм аналогичный - создание ключа, поиск, вывод, если нашли. Если нет, то формируем список постов и сохраняем в хранилище. Отличие только в dependency.

Так как дата изменения поста - это целое (ну или легко может быть приведено к этому типу), то в качестве зависимости можно сохранить значение суммы дат изменения всех опубликованных постов. Если изменится какой-то пост, изменится дата, изменится и сумма.

$dependency = new \yii\caching\DbDependency([
    'sql' => 'SELECT SUM(updated_at) AS sum_updated FROM post WHERE status=' .
        Post::STATUS_PUBLISHED,
]);

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

Memcached

Если необходимо, чтобы вывод страниц был еще быстрее, можно воспользоваться другим типом хранилища. Например memcache. Менять при этом придется только конфигурацию так как все типы хранилищ реализуют один интерфейс.

'cache' => [
    /* 'class' => 'yii\caching\FileCache', */
    'class' => 'yii\caching\MemCache',
    'servers' => [
        [
            'host' => 'localhost',
            'port' => 11211,
        ],
    ],
    'useMemcached' => true,
],

Кроме того на сервере нужен демон memcached, и модуль поддержки memcached в php7.

$ sudo apt-get install memcached
$ sudo apt-get install php-memcached
$ sudo /etc/init.d/apache2 restart

Fragment Caching

Сохранять страницу полностью, вряд ли можно считать хорошей идеей. На странице может быть множество различных элементов, например виджет рубрик и не смотря на то, что вы только что добавили новую рубрику, она почему-то не появится в списке. Все очевидно - пост не изменился и страница продолжает выводится из хранилища.

Решение простое - сохранять подготовленный контент фрагментами, непосредственно в представлениях. Например frontend/views/post/_view.php

<?php if($this->beginCache("_view-{$model->id}", [
    'dependency' => [
        'class' => '\yii\caching\DbDependency',
        'sql' => ('SELECT updated_at FROM post WHERE id=' . $model->id),
    ],
    'variations' => [\Yii::$app->language],
])): ?>
    <div class='post-preview'>
        ...
    </div>
    <?php $this->endCache(); ?>
<?php endif; ?>

Заключение

Сохранять в хранилище можно любые результаты предварительной обработки. Данные разные, варианты хранилищ тоже, а подход один.

Оставьте комментарий