Caching de Fragmentos

Caching de fragmentos refere-se ao ato de armazenar em cache apenas um fragmento de uma página. Por exemplo, se uma página exibe em uma tabela o resumo anual de vendas, podemos armazenar essa tabela em cache para eliminar o tempo necessário para gera-la em cada requisição.

Para utilizar o caching de fragmentos, utilizamos os métodos CController::beginCache() e CController::endCache() na visão de um controle. Esses dois métodos marcam, respectivamente, o início e termino do conteúdo da página que deve ser armazenado em cache. Assim como no caching de dados, precisamos de um ID para identificar o fragmento armazenado.

...outro conteúdo HTML...
<?php if($this->beginCache($id)) { ?>
...conteúdo que deve ser armazenado...
<?php $this->endCache(); } ?>
...outro conteúdo HTML...

No código acima, se o método beginCache() retornar false, o conteúdo já armazenado no cache será exibido, caso contrário, o conteúdo dentro do if será executado e, então, armazenado quando o método endCache() for executado. Na realidade, os métodos beginCache() e endCache() encapsulam os métodos de mesmo nome existentes no widget COutputCache. Sendo assim, as opções de caching podem ser os valores iniciais para qualquer uma das propriedades de COutputCache.

Duração

Provavelmente a opção mais utilizada seja a duration, que especifica por quanto tempo o conteúdo deve ser mantido válido no cache. Seu funcionamento é similar ao parâmetro de tempo de expiração do método CCache::set(). O código a seguir armazena em cache o fragmento por, no máximo, uma hora:

...outro conteúdo HTML...
<?php if($this->beginCache($id, array('duration'=>3600))) { ?>
...conteúdo a ser armazenado...
<?php $this->endCache(); } ?>
...outro conteúdo HTML...

Se não informamos a duração, seu valor padrão será 60, indicando que o conteúdo do cache deve ser invalidado depois de 60 segundos.

Dependência

Assim com o caching de dados, fragmentos de conteúdo armazenados em cache também podem ter dependências. Por exemplo, o conteúdo de um post pode se exibido, caso ele tenha sido alterado ou não.

Pada especificar uma dependência, devemos utilizar a opção dependency, que pode ser um objeto implementando a interface ICacheDependency ou um vetor de configuração que pode ser utilizado para gerar a dependência. O código a seguir especifica que o fragmento depende da alteração do valor da coluna lastModified:

...outro conteúdo HTML...
<?php if($this->beginCache($id, array('dependency'=>array(
        'class'=>'system.caching.dependencies.CDbCacheDependency',
        'sql'=>'SELECT MAX(lastModified) FROM Post')))) { ?>
...conteúdo a ser armazenado no cache...
<?php $this->endCache(); } ?>
...outro conteúdo HTML...

Variação

O conteúdo armazenado em cache pode sofrer variações de acordo com alguns parâmetros. Por exemplo, o perfil pessoal pode ter aparências diferentes para diferentes usuários. Para armazenar em cache o conteúdo do perfil, seria interessante que a cópia em cache varie de acordo com os IDs dos usuários. Isso significa que devemos utilizar IDs diferentes ao chamar o método beginCache().

Em vez de deixar para os desenvolvedores o controle sobre a variação desses IDs, a classe COutputCache já possui esse recurso. Abaixo, um resumo:

  • varyByRoute: mudando seu valor para true, o conteúdo em cache irá variar de acordo com a rota. Dessa forma, cada combinação de controle/ação terá seu conteúdo armazenado em cache separadamente.

  • varyBySelection: mudando seu valor para true, podemos fazer com que o conteúdo em cache varie de acordo com os IDs da sessão. Dessa forma, cada sessão de usuário pode ter conteúdos diferentes e todos servidos através do cache.

  • varyByParam: ao atribuir um vetor de nomes a essa opção, podemos fazer com que o conteúdo do cache varie de acordo com valores passados através de GET. Por exemplo, se uma página exibe o conteúdo de um post de acordo com a variável GET id, podemos definir varyByParam como array('id'), assim podemos armazenar em cache o conteúdo de cada post. Sem esse tipo de variação, poderiamos apenas armazenar um único post.

  • varyByExpression: ao atribuir uma expressão PHP a essa opção, podemos fazer com que o conteúdo do cache varie de acordo com o resultado dessa expressão. Essa opção está disponível a partir da versão 1.0.4.

Tipos de Requisição

As vezes, queremos que o cache de fragmentos esteja habilitado somente para certos tipos de requisições. Por exemplo, para uma página exibindo um formulário, queremos armazenar o formulário apenas na primeira vez em que a página é requisitada (via GET). Nas exibições seguintes (via POST), o formulário não deve ser armazenado porque ele pode conter os dados informados pelos usuários. Para isso, podemos utilizar a opção requestTypes:

...outro conteúdo HTML...
<?php if($this->beginCache($id, array('requestTypes'=>array('GET')))) { ?>
...conteúdo a ser armazenado...
<?php $this->endCache(); } ?>
...outro conteúdo armazenado...

1. Caching Aninhado

O caching de fragmentos pode ser aninhado. Isso é, um fragmento em cache que está dentro de um outro fragmento, também em cache. Por exemplo, os comentários estão em cache, junto do conteúdo do post que também está em cache.

...outro conteúdo HTML...
<?php if($this->beginCache($id1)) { ?>
...conteúdo externo em cache...
    <?php if($this->beginCache($id2)) { ?>
    ...conteúdo interno em cache...
    <?php $this->endCache(); } ?>
...conteúdo externo em cache...
<?php $this->endCache(); } ?>
...outro conteúdo em cache...

Diferentes opções de caching podem ser utilizadas para os caches aninhados. Por exemplo, os caches interno e o externo, no exemplo acima, podem ter durações diferentes. Quando os dados armazenados em cache do conteúdo externo tornarem-se inválidos, o cache do conteúdo interno ainda vai conter seu fragmento válido. Entretanto, o inverso não é verdadeiro. Se o conteúdo externo contém dados válidos, ele sempre irá fornecer a cópia em cache, mesmo que o cache do conteúdo interno já tenha expirado. Você deve ter cuidado na definição das durações ou as dependências dos caches aninhados, caso contrário, os fragmentos desatualizados internas podem ser mantidos no fragmento exterior.

$Id$

Be the first person to leave a comment

Please to leave your comment.