0 follower

Кэширование фрагментов

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

Для использования кэширования фрагментов мы вызываем методы CController::beginCache() и CController::endCache() в скрипте представления контроллера. Эти два метода являются метками начала и конца содержимого страницы, которое должно быть кэшировано. Как и в кэшировании данных, нам нужен идентификатор для определения кэшируемого фрагмента.

...другое HTML-содержимое...
<?php if($this->beginCache($id)) { ?>
...кэшируемое содержимое...
<?php $this->endCache(); } ?>
...другое HTML-содержимое...

В коде выше, если метод beginCache() возвращает false, то кэшированное содержимое будет автоматически вставлено в данное место, иначе, содержимое внутри выражения if будет выполнено и сохранено в кэше, когда будет вызван метод endCache().

1. Параметры кэширования

Вызывая метод beginCache(), мы можем передать в качестве второго параметра массив, содержащий параметры кэширования для управления кэшированием фрагмента. Фактически, методы beginCache() и endCache() являются удобной оберткой виджета COutputCache. Поэтому, параметры кэширования могут быть начальными значениями для любых свойств виджета COutputCache.

Длительность (срок хранения)

Наверное, наиболее часто используемым параметром является duration, который определяет, насколько долго содержимое кэша будет оставаться действительным (валидным). Это похоже на параметр срока действия метода CCache::set(). Код ниже кэширует фрагмент на время не более часа:

...другое HTML-содержимое...
<?php if($this->beginCache($id, array('duration'=>3600))) { ?>
...кэшируемое содержимое...
<?php $this->endCache(); } ?>
...другое HTML-содержимое...

Если мы не установим длительность (срок хранения), она будет равна значению по умолчанию (60 секунд). Это значит, что кэшированное содержимое станет недействительным через 60 секунд.

Зависимость

Как и кэширование данных, кэшируемое содержимое фрагмента тоже может иметь зависимости (dependency). Например, отображение содержимого сообщения зависит от того, изменено или нет это сообщение.

Для определения зависимости, мы устанавливаем параметр dependency, который может быть либо объектом, реализующим интерфейс ICacheDependency, либо массивом настроек, который может быть использован для генерации объекта зависимости. Следующий код определяет содержимое фрагмента, зависящее от изменения значения столбца lastModified:

...другое HTML-содержимое...
<?php if($this->beginCache($id, array('dependency'=>array(
        'class'=>'system.caching.dependencies.CDbCacheDependency',
        'sql'=>'SELECT MAX(lastModified) FROM Post')))) { ?>
...кэшируемое содержимое...
<?php $this->endCache(); } ?>
...другое HTML-содержимое...

Вариации (изменения)

Кэшируемое содержимое может быть изменено в соответствии с некоторыми параметрами. Например, личный профиль может по-разному выглядеть для разных пользователей. Для кэширования содержимого профиля мы бы хотели, чтобы кэшированная копия была различной в соответствии с идентификатором пользователя. По-существу, это значит, что мы должны использовать разные идентификаторы при вызове метода beginCache().

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

  • varyByRoute: если установлено в значение true, кэшированное содержимое будет изменяться в соответствии с настройками маршрута. Поэтому, каждая комбинация запрашиваемого контроллера и действия будут иметь разное кэшированное содержимое;

  • varyBySession: если установлено в значение true, кэшированное содержимое будет изменяться в соответствии с идентификатором сессии. Поэтому, каждая пользовательская сессия может видеть различное содержимое и получать его из кэша;

  • varyByParam: если установлено в качестве массива имен, кэшированное содержимое будет изменяться в соответствии с определенными GET параметрами. Например, если страница отображает содержимое сообщения в зависимости от GET-параметра id, мы можем определить varyByParam в виде массива array('id') и затем кэшировать содержимое каждого сообщения. Без такой вариации, мы могли бы кэшировать только одно сообщение;

  • varyByExpression: если установлено в качестве выражения PHP, кэшированное содержимое будет изменяться в соответствии с результатом данного выражения PHP. Доступно с версии 1.0.4.

Типы запросов

Иногда мы хотим, чтобы кэширование фрагмента было включено только для некоторых типов запроса. Например, страницу с формой мы хотим кэшировать только тогда, когда она инициализирована (GET запросом) (не заполнена). Любое последующее отображение формы (получившееся POST запросом) (заполненная форма) не должно быть кэшировано, потому что может содержать данные, введенные пользователем. Чтобы так сделать, мы определяем параметр requestTypes:

...другое HTML содержмое...
<?php if($this->beginCache($id, array('requestTypes'=>array('GET')))) { ?>
...кэшируемое содержимое...
<?php $this->endCache(); } ?>
...другое HTML содержмое...

2. Вложенное кэширование

Кэширование фрагментов может быть вложенным. Это значит, что кэшированный фрагмент окружен более крупным фрагментом (содержится в нем), который тоже кэшируется. Например, комментарии кэшированы во внутреннем фрагменте кэша, и они же кэшированы вместе с содержимым сообщения во внешнем фрагменте кэша.

...другое HTML содержмое...
<?php if($this->beginCache($id1)) { ?>
...внешнее кэшируемое содержимое...
    <?php if($this->beginCache($id2)) { ?>
    ...внутреннее кэшируемое содержимое...
    <?php $this->endCache(); } ?>
...внешнее кэшируемое содержимое...
<?php $this->endCache(); } ?>
...другое HTML содержмое...

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