Este artigo ensina como utilizar o servidor de cache Memcached com o framework em PHP Zend Framework. O Libmemcached é uma biblioteca em C que faz a comunicação com o servidor de Memcached e para isso é necessário a biblioteca memcached do PECL (PHP Extension Community Library) – esta lib é instanciada através de código PHP na aplicação em Zend Framework. O ambiente utilizado é Linux (tanto para o servidor web quanto para o servidor de cache).
Passo 1: Instalação Memcached
No Ubuntu, para instalar o servidor Memcached usando o apt-get:
sudo apt-get install memcached
Por padrão, o servidor Memcahed irá atender na porta 11211. Caso você tenha problemas com o apt-get, será necessário baixar o Memcached do site oficial (ver link em Referências), descompactar, compilar e instalar.
Passo 2: Instalação Libmemcached
Instale a Libmemcached. Esta library é uma API em C para se comunicar com o servidor Memcached. Depois, baixe e instale diretamente do site oficial (ver link em Referências). Será necessário descompactar, compilar e instalar o arquivo .tar.gz disponibilizado para download no site oficial.
Uma opção mais fácil é usar o apt-get do Linux:
sudo apt-get install libmemcached5
Passo 3: Instalação lib memcached do PECL
Instale a lib cliente que se comunica com a Libmemcached, em nosso caso utilizamos a lib memcached do PECL. Para instalar, foi necessário compilar o arquivo fonte e executar alguns procedimentos:
- Faça o download da lib memcached no site oficial do PECL (ver link em Referencias);
- Faça a instalação e lembre-se de rodar o comando configure informando o diretório da Libmemcached (Passo 2) – geralmente ela é instalada sob o diretorio “/usr/lib”. No meu caso, utilizei o comando configure da seguinte forma: ./configure –with-libmemcached-dir=/usr/lib;
- Copiar o arquivo gerado “memcached.so”. Este arquivo será gerado na pasta “/modules”, para a pasta de libs do PHP, por exemplo: “/usr/lib/php5/20100525+lfs/”;
- Copiar o conteúdo do arquivo memcached.ini para o arquivo php.ini do PHP – geralmente fica em “/etc/php5”.
Opção mais simples, mas que não funcionou comigo, é utilizar o apt-get:
sudo apt-get install php5-memcached
Passo 4: Rode um exemplo PHP simples
Reinicie o servidor web e rode um exemplo em PHP simples para testar. Exemplo a seguir:
Arquivo “memcached.php”
$mc = new Memcached();
$mc->addServer("localhost", 11211);
$mc->set("Nome", "Necessario para uma nova tentativa de ação!");
$mc->set("Quem", "Alguem...");
$mc->set("foo", "Hello!");
$mc->set("bar", "Memcached...");
$arr = array(
$mc->get("Nome"),
$mc->get("Quem") ,
$mc->get("foo"),
$mc->get("bar")
);
var_dump($arr);
Rode no browser: http://localhost/memcached.php
Passo 5: Rode um exemplo com Zend_Cache
Exemplo com o Zend_Cache. Instanciando a classe de configuração do Zend_Cache no Bootstrap do Zend Framework e criando a classe que configura a instância do Zend_Cache da sua aplicação.
A classe a seguir, BootstrapCache, configura e instancia a classe Zend_Cache, responsável por inserir, recuperar e apagar dados do servidor de cache. A classe BootstrapCache deve ser chamada de forma estática no bootstrap (/application/Bootstrap.php) do Zend Framework, lembrando que este artigo cobre a versão 1.12 do ZF. Observe:
Arquivo “/application/Bootstrap.php”
/**
* Inicializa camada de cache: filesystem ou memcached
*/
protected function _initCache()
{
//pattern Command
BootstrapCache::execute();
}
A classe BootstrapCache é responsavel pela configuração do cache da aplicação.
Arquivo “/lib/BootstrapCache.php”
class BootstrapCache {
/**
* host para instancia do server Memcached
*
* @var string
*/
protected $hostMemcache;
/**
* configuracoes para cache Conteudo site
*/
protected $tipoCacheConteudo; //Libmemcached, File, None
protected $lifetimeConteudo;
protected $pathCacheConteudo;
public function __construct() {}
/**
* desgin pattern Command
*/
public static function execute()
{
//instancia cache:
$camadaCache = new BootstrapCache();
//recupera configuracao do Cache no config.ini
$camadaCache->setHostMemcache(Zend_Registry::get('config')->cache->host->memcached);
$camadaCache->setTipoCacheConteudo(Zend_Registry::get('config')->cache->Conteudo->tipo);
$camadaCache->setLifetimeConteudo(Zend_Registry::get('config')->cache->Conteudo->lifetime);
$camadaCache->setPathCacheConteudo(Zend_Registry::get('config')->cache->Conteudo->pathcache);
$camadaCache->cacheConteudo();
}
/**
* @return array
*/
private function configApp()
{
$hostMemcache = $this->getHostMemcache();
//dir do filesystem
$path_cache = $this->getPathCacheConteudo();
switch ($this->getTipoCacheConteudo())
{
case 'File':
$appfrontendConteudo = array(
'lifetime' => $this->getLifetimeConteudo(), //seconds
'automatic_serialization' => true,
//'debug_header' => true,
);
$appbackendConteudo = array(
'cache_dir' => $path_cache
);
break;
case 'Libmemcached':
case 'Memcached':
$appfrontendConteudo = array(
'lifetime' => $this->getLifetimeConteudo(), //seconds
'automatic_serialization' => true,
'caching' => true,
);
$appbackendConteudo = array(
'servers' => array(
array(
'host' => $hostMemcache,
'port' => 11211,
'weight' => 1
)
),
'compression' => false
);
break;
} //end switch
return array ( 'Conteudo' => array(
'frontend' => $appfrontendConteudo,
'backend' => $appbackendConteudo
),
);
}
/**
* faz cache de conteudo site
*/
public function cacheConteudo()
{
//seta configuracoes para o cache
$arrConfig = $this->configApp();
$appfrontend = $arrConfig['Conteudo']['frontend'];
$appbackend = $arrConfig['Conteudo']['backend'];
$appcache = Zend_Cache::factory('Core',
$this->getTipoCacheConteudo(),
$appfrontend,
$appbackend
);
// adiciona cache no Registry
Zend_Registry::set('cache_Conteudo', $appcache);
}
//codigo omitido
//getters e setters
}
Passo 6: Classe ConteudoCache
Para gravar e recuperar o conteúdo do Memcached utilize o exemplo da classe a seguir:
Arquivo “/lib/ConteudoCache.php”
/**
* Metodos que instanciam Zend_Cache para fazer cache que areas do site
*
* @author esilva
*/
class ConteudoCache {
/**
* @var Zend_Cache_Core
*/
protected $cache;
public function __construct()
{
//instancia Zend_Cache_Core
$this->cache = Zend_Registry::get('cache_Conteudo');
}
/**
* faz cache de areas de conteudo do site
*
* @param DbTable_ConteudoRow $dbtableConteudoRow
* @return array
*/
public function recuperaOuGravaConteudoNoCache(DbTable_ConteudoRow $dbtableConteudoRow, $idConteudo)
{
$nameCache = "conteudo_".$idConteudo;
$blocoCacheModel = $this->cache->load($nameCache);
$msgCache = "pegou do cache";
if (!$blocoCacheModel)
{
$blocoCacheModel = $dbtableQuestionnaireRow->getAll($idConteudo);
$this->cache->save($blocoCacheModel, $nameCache);
$msgCache = "NÂO pegou do cache";
}
return $blocoCacheModel;
}
}
O metodo “recuperaOuGravaConteudoNoCache” da classe “ConteudoCache” recebe como parâmetro uma instância DbTable, que é basicamente um fetchall de uma tabela do banco de dados. O parâmetro $idConteudo é o id único que identifica o conteúdo que está sendo cacheado ou se deseja recuperar do cache.
Informações de configuração, como o host do Memcached, tipo de cache (Libmemcached ou File), tempo de vida do cache e caminho para o filesystem, são armazenados no arquivo “config.ini” da sua aplicação Zend Framework. Se vocês observaram bem, o código também estaápreparado para cachear no filesystem da aplicação, sendo necessário apenas passar a string “FILE” na configuração do parâmetro “cache.conteudo.tipo”, no arquivo “config.ini”.
Passo 7: Arquivo config.ini
Os dados de configuração do cache estão no arquivo “config.ini” (/application/configs/config.ini):
Arquivo “/application/configs/config.ini”
cache.host.memcached = "localhost"; cache.conteudo.tipo = "Libmemcached"; //File //Libmemcached //None cache.conteudo.lifetime = 900; //15min cache.conteudo.pathcache = APPLICATION_PATH_CACHE "/cacheConteudo";
Repare que o método estático “execute” da classe BootstrapCache recupera os dados do arquivo “config.ini”, utilizando o Zend_Registry.
Passo 8: Classe Model_ConteudoQuestoes
Na classe model de conteúdo será necessário instanciar a classe ConteudoCache e informar o Id do conteúdo que deve ser recuperado.
Arquivo “/application/model/ConteudoQuestoes.php”
class Model_ConteudoQuestoes
{
//
// codigo omitido
//
public function cacheOrModelConteudoId($conteudoId)
{
$conteudoCache = new ConteudoCache();
$resultado = $conteudoCache->recuperaOuGravaConteudoNoCache($this, $conteudoId)
return $resultado;
}
public function getAll($idConteudo)
{
// codigo omitido
// $fetchAll recupera dados de conteudo do banco de dados
//retorno com conteudo do banco dados
return $fetchAll;
}
}
O parâmetro $this informado no metodo “recuperaOuGravaConteudoNoCache” refere-se a própria classe model onde se encontra o método “cacheOrModelConteudoId”. Ele é ‘injetado’ na classe ConteudoCache.
Dentro da classe ConteudoCache, no metodo “recuperaOuGravaConteudoNoCache”, é feita a chamada a “$dbtableQuestionnaireRow->getAll();” caso o conteúdo não seja encontrado no servidor de cache. Essa chamada é o mesmo que $this->getAll() na classe Model_ConteudoQuestoes.
Na action do controller que recebe o array (fetchall) de conteúdo do banco de dados faça uma chamada ao método “cacheOrModelConteudoId” informando o Id de conteúdo que será recuperado e enviado para a view.
Por exemplo:
$conteudoId = 101; //Informacoes das questões para o cliente $this->view->conteudoParaCliente = $this->ModelConteudo->cacheOrModelConteudoId($conteudoId);
Esta chamada na action retorna o conteúdo de questões para a view, porém, este conteúdo poderá ser do banco de dados ou do Memcached. O método “cacheOrModelConteudoId” é responsável apenas por devolver o conteúdo para a action, que então disponibiliza o conteúdo para a view.
Conclusão
Este é um passo a passo para usuários com experiência em Linux e Zend Framework. O objetivo foi informar os passos necessários e o que é preciso para se chegar ao objetivo final, que é obter um servidor de cache Memcached configurado e recebendo requisições de uma aplicação web desenvolvida em Zend Framework.



