Кешування сторінок
==================

Кешування сторінок — це кешування всього вмісту сторінки. Кешування сторінок може зустрічатися в різних місцях. Наприклад, обравши відповідний сторінці заголовок, браузер користувача може кешувати сторінку, яка переглядається, на деякий час. Веб-додаток також може сам зберігати вміст сторінки у кеші. У цьому підрозділі ми розглянемо саме другий варіант.

Кешування виводу
----------------

Кешування сторінки може бути розглянуто як окремий випадок [кешування фрагмента](/doc/guide/caching.fragment). Через те, що вміст сторінки часто генерується застосуванням макета до представлення, кешування не буде працювати, якщо ми просто викличемо в макеті методи [beginCache()|CBaseController::beginCache] та [endCache()|CBaseController::endCache]. Причина цього у тому, що макет застосовується при виклику метода [CController::render()] *після* формування вмісту представлення.

Для кешування всієї сторінки ми повинні пропустити етап формування вмісту сторінки. Для виконання цього завдання ми можемо використовувати клас [COutputCache] як [фільтр](/doc/guide/basics.controller#filter) дії. У коді нижче показано, як можна сконфігурувати фільтр кешу:

~~~
[php]
public function filters()
{
	return array(
		array(
			'COutputCache',
			'duration'=>100,
			'varyByParam'=>array('id'),
		),
	);
}
~~~

Вищенаведена конфігурація фільтру створює фільтр, який застосовується до всіх дій контролера. Ми можемо обмежити цю поведінку одним або кількома діями, використовуючи оператор `+`. Докладніше з роботою фільтрів можна ознайомитися в темі [фільтри](/doc/guide/basics.controller#filter).

> Tip|Підказка: Ми можемо використовувати клас [COutputCache] як фільтр, оскільки він успадковує клас [CFilterWidget], тобто обидва ці класу одночасно є і віджетами, і фільтрами. Фактично, спосіб роботи віджету дуже схожий на роботу фільтра: віджет (фільтр) виконується до того, як будь-який вкладени вміст (дія) буде сформовано (виконано), а виконання віджету (фільтра) закінчується після того, як вкладений вміст (дія) буде сформовано (виконано).

Кешування HTTP
--------------

На додаток до кешуванню простого виводу данних дії, Yii надає [CHttpCacheFilter] (починаючи з версії 1.1.11). 
Цей фільтр допомагає у налаштуванні вищезазначених заголовків повідомити клієнту, що зміст сторінки не змінився з моменту останнього запиту, тому сервер не буде повторно передавати зміст. 
[CHttpCacheFilter] може бути встановлений ​​аналогічно до [COutputCache]:
~~~
[php]
public function filters()
{
    return array(
        array(
            'CHttpCacheFilter + index',
            'lastModified'=>Yii::app()->db->createCommand("SELECT MAX(`update_time`) FROM {{post}}")->queryScalar(),
        ),
    );
}
~~~

Вищенаведений код встановлює останню дату як значення заголовку `Last-Modified`, коли повідомлення було оновлено.
Ви також можете використовувати [CHttpCacheFilter::lastModifiedExpression] для встановлення заголовку `Last-Modified`, використовуючи вираз php.

> Tip|Підказка: Обидва, [CHttpCacheFilter::lastModifiedExpression] та 
[CHttpCacheFilter::lastModified] можуть бути цілим числом, яке представляє Unix timestamp, або довільним рядком, 
що представляє *зрозумілу* дату. 
До тих пір, поки значення можливо розібрати через [strtotime()](http://php.net/manual/function.strtotime.php), 
ніяка додаткова конвертація не потрібна.

Заголовок "Entity Tag" (або скорочено `ETag`) може бути встановлений таким же чином, через [CHttpCacheFilter::etagSeed] та
[CHttpCacheFilter::etagSeedExpression], відповідно.
Обидва будуть серіалізовані (так що ви зможете використовувати або одне значення, або весь масив) і використовуються для генерації base64-кодованого SHA1 хеша в лапках, який виступає у якості контенту для заголовка `ETag`.
Це відрізняється від того, як [веб-сервер Apache](http://httpd.apache.org) та інші створюють свої ETags. 
Однак, цей метод цілком відповідає вимогам RFC і виявився більш прийнятним для використання у framework.

> Note|Примітка: Для того, щоб відповідати
[RFC 2616, розділу 13.3.4](http://tools.ietf.org/html/rfc2616#section-13.3.4),
[CHttpCacheFilter] буде надсилати заголовки `ETag` та `Last-Modified`, якщо вони обидва можуть бути згенеровані.
Відтак, вони обидва будуть використовуватися для перевірки кешу при відправці клієнту.

Відколи *entity tags* це хеші, вони дозволяють більш складних і/або більш точних стратегій кешування, 
ніж заголовки `Last-Modified`. Наприклад, ETag може бути визнаний недійсним, якщо сайт змінив свою тему.

> Tip|Підказка: *Важкі* вирази для [CHttpCacheFilter::etagSeedExpression] можуть суперечити меті [CHttpCacheFilter]
і запровадити зайве навантаження, так як вони мають бути повторно обчислені при кожному запиті.
Спробуйте знайти простий вираз, який визнає недійсним кеш, якщо зміст сторінки було змінено.

### SEO наслідки

Як правило, пошукові боти поважають заголовки кешу. 
Оскільки деякі сканери мають обмеження на кількість сторінок в межах домену, 
які вони обробляють за певний проміжок часу, 
запровадження заголовків кешу може допомогти індексації сайту, 
оскільки вони зменшують кількість сторінок, які повинні бути оброблені.