Кешування фрагментів
====================

Кешування фрагментів відноситься до кешування фрагментів веб-сторінки. Наприклад, якщо сторінка відображає в таблиці сумарні 
річні продажі, ви можете зберегти цю таблицю в кеші з метою економії часу, необхідного для створення таблиці при кожному запиті. 
Кешування фрагментів засноване на [кешуванні даних](caching-data.md).

Для кешування фрагментів використовуйте наступний код у [представленні](structure-views.md):

```php
if ($this->beginCache($id)) {

    // ... тут створюємо зміст ...

    $this->endCache();
}
```

Таким чином, розташуйте логіку генерації вмісту у комбінацію викликів [[yii\base\View::beginCache()|beginCache()]] та
[[yii\base\View::endCache()|endCache()]]. Якщо вміст буде знайдено у кеші, [[yii\base\View::beginCache()|beginCache()]]
відобразить закешований вміст і поверне false, оминаючи генерацію вмісту.
В іншому випадку, буде виконано логіку генерації вмісту і з викликом [[yii\base\View::endCache()|endCache()]]
згенерований вміст буде записаний до кешу.

Подібно до [кешування даних](caching-data.md), для кешування фрагментів необхідний унікальний ідентифікатор 
для визначення кешувального фрагмента.


## Параметри кешування <a name="caching-options"></a>

Ви можете вказати додаткові параметри про кешуванні фрагментів, передавши масив опцій в якості другого параметра метода
[[yii\base\View::beginCache()|beginCache()]]. За лаштунками, цей масив параметрів буде використано для налаштування віджета
[[yii\widgets\FragmentCache]], який реалізує фактичну функціональність кешування фрагментів.


### Тривалість <a name="duration"></a>

Мабуть найбільш часто використовуваною опцією кешування фрагмента є [[yii\widgets\FragmentCache::duration|duration]].
Вона визначає на скільки секунд зміст може залишатися дійсним у кеші. Код нижче кешує фрагмент не більше, ніж на одну:

```php
if ($this->beginCache($id, ['duration' => 3600])) {

    // ... тут створюємо зміст ...

    $this->endCache();
}
```

Якщо опцію тривалості не задано, то вона прийме значенне за замовчування (60), що означає, що вміст в кеші стане недійсним через 60 секунд.


### Залежності <a name="dependencies"></a>

Подібно до [кешування даних](caching-data.md#cache-dependencies), фрагмент вмісту у кеші також може мати залежності.
Наприклад, вміст поста, що відображається, залежить від того, чи був він змінений.

Для визначення залежності, встановіть опцію [[yii\widgets\FragmentCache::dependency|dependency]], 
яка може бути або обʼєктом [[yii\caching\Dependency]] або масивом налаштувань для створення обʼєкта залежностей.
Наступний код визначає, що вміст фрагмента залежить від зміни значення стовпця `updated_at`:

```php
$dependency = [
    'class' => 'yii\caching\DbDependency',
    'sql' => 'SELECT MAX(updated_at) FROM post',
];

if ($this->beginCache($id, ['dependency' => $dependency])) {

    // ... тут створюємо зміст ...

    $this->endCache();
}
```


### Варіації <a name="variations"></a>

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

Щоб вказати варіації кешу, встановіть опцію [[yii\widgets\FragmentCache::variations|variations]], 
яка повинна бути масивом скалярних значень, кожне з яких представляє певний коефіцієнт варіації.
Наприклад, щоб кешувати вміст у залежності від мови додатка, ви можете використовувати наступний код:

```php
if ($this->beginCache($id, ['variations' => [Yii::$app->language]])) {

    // ... тут створюємо зміст ...

    $this->endCache();
}
```


### Перемикання кешування <a name="toggling-caching"></a>

Іноді, ви можете захотіти увімкнути кешування фрагмента тільки за певних умов. Наприклад, для сторінки, яка відображає форму, 
ви хочете кешувати тільки форму при її початковому запиті (через GET-запит). Будь-яке подальше відображення (через POST-запит)
форми не повинне кешуватися, тому що форма може містити дані, що ввів користувач.
Щоб зробити це, ви можете встановити опцію [[yii\widgets\FragmentCache::enabled|enabled]] наступним чином:

```php
if ($this->beginCache($id, ['enabled' => Yii::$app->request->isGet])) {

    // ... тут створюємо зміст ...

    $this->endCache();
}
```


## Вкладене кешування <a name="nested-caching"></a>

Кешування фрагментів може бути вкладеним. Тобто, кешований фрагмент може бути укладений в інший фрагмент, що також кешується.
Наприклад, коментарі кешируются у внутрішньому фрагменті кешу, і вони ж кешуються разом із вмістом поста у зовнішньому 
фрагменті кеша. Наступний код показує, як два кеша фрагментів можуть бути вкладеними:

```php
if ($this->beginCache($id1)) {

    // ...логіка створення контента...

    if ($this->beginCache($id2, $options2)) {

        // ...логіка створення контента...

        $this->endCache();
    }

    // ...логіка створення контента...

    $this->endCache();
}
```

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


## Динамічний зміст <a name="dynamic-content"></a>

При використанні кешування фрагментів, ви можете зіткнутися із ситуацією, коли великий фрагмент змісту є відносно статичним,
за винятком одного або декількох місць. Наприклад, заголовок сторінки може відображатися у головному меню разом 
з імʼям поточного користувача. Інша проблема в тому, що закешований зміст може містити код PHP, який повинен 
виконуватися при кожному запиті (наприклад, код для реєстрації пакету ресурсів). Обидві ці проблеми можуть бути 
вирішені за допомогою так званої функції *динамічного змісту*.

Динамічний зміст означає фрагмент виведення, який не повинен кешуватися, навіть якщо він укладений у кешування фрагментів.
Для того, щоб зробити зміст динамічним постійно, він повинен бути створений за допомогою деякого PHP коду для кожного запиту,
навіть якщо зміст віддаєтся із кеша.

Ви можете викликати [[yii\base\View::renderDynamic()]] в кеші фрагмента для вставки динамічного контенту у потрібне місце,
як у прикладі нижче:

```php
if ($this->beginCache($id1)) {

    // ...логіка створення контента...

    echo $this->renderDynamic('return Yii::$app->user->identity->name;');

    // ...логіка створення контента...

    $this->endCache();
}
```

Метод [[yii\base\View::renderDynamic()|renderDynamic()]] бере деяку частину коду PHP в якості параметра.
Значення, що повертається від коду PHP, трактується як динамічний зміст. Цей код PHP буде виконуватися при кожному запиті,
незалежно від того, чи віддається фрагмент із кешу або ні.
