Henrique Barcelos 290 Denunciar post Postado Novembro 2, 2012 Bom, galera... Ainda no desenvolvimento do meu "framework", estou criando um sistema de cache para o backend. Por enquanto, ele está bem simples: o arquivo de cache trata-se de um arquivo comum de texto (apenas mudo a extensão). A "sacada" é que a primeira linha do arquivo contém o UNIX timestamp que indica a validade do arquivo. Ao ler um arquivo do cache, caso o timestamp seja menor que o timestamp atual ele é ignorado. Bom, até aí tudo lindo, funciona bem. Eu até criei uma fachada (Facade) para simplifica o uso do cache. A questão é que tudo é manual, desde a definição do diretório do cache até o seu nome. Isso acaba complicando um pouco quando eu preciso compartilhar caches entre diferentes classes. Como exemplo, imagine que eu tenho uma área administrativa de uma aplicação e uma área pública. Ao buscar o conteúdo pela primeira vez no site público, o cache será realizado pela aplicação, salvando o HTML gerado em um arquivo predefinido. E se eu alterar o conteúdo através da área administrativa, qual o melhor jeito de invalidar o cache? Deixar a aplicação livre pra selecionar pra onde o cache vai e o seu nome me dá a possibilidade de compartilhar nomes de diretórios e arquivos utilizando propriedades e constantes, mas a coisa fica meio bagunçada se o desenvolvedor não seguir um padrão. Como se trata, em teoria, de um Framework, não basta o "eu sei como utilizar, não vou fazer cagada, deixa como está". Vou postar só o código da fachada, que acredito ser o mais importante. Caso alguém veja necessidade, posto também o código mais "baixo nível". <?php /** * Controlador simples de cache * @author <a href="mailto:rick.hjpbacelos@gmail.com">Henrique Barcelos</a> */ class Cache_Facade extends Cache_Facade_Abstract { /** * @var int */ const FILE_APPEND = FILE_APPEND; /** * @var NULL */ const FILE_OVERWRITE = null; /** * @var string */ const CACHE_EXTENSION = 'cache'; /** * Armazena o diretório de cache. * @var string */ private $_cacheDir; /** * Construtor. * * @param string $cacheDir [OPTIONAL] : o diretório-base para os arquivos de cache */ public function __construct($cacheDir = null) { if($cacheDir !== null) { $this->setCacheDir($cacheDir); } } /** * @see Cache_Facade_Abstract::set() */ public function set($directory, $fileName, $contents, $expires = null, $flag = null) { if(!self::isCacheEnabled()) { throw new Cache_DisabledException('O cache foi desabilitado nesta aplicação!'); } try { $dir = new FileSystem_Directory($this->getCacheDir().$directory); } catch (FileSystem_Directory_Exception $e) { throw new Cache_WriteException(sprintf('Problemas ao criar do diterório de cache "%s"', $directory)); } $path = $dir->getPath().$fileName. '.' . self::CACHE_EXTENSION; if(Cache_File::isFile($path) && !Cache_File::isWritable($path)) { throw new Cache_WriteException('Permissão negada ao tentar escrever no arquivo de cache ' . $path); } if($contents instanceof Serializable) { $contents = $contents->serialize(); } else { $contents = serialize($contents); } try { $mode = $flag == self::FILE_OVERWRITE ? Cache_File::LOCK_EX : Cache_File::LOCK_EX | Cache_File::APPEND; $cacheFile = new Cache_File($path); $cacheFile->setExpiration($expires); return $cacheFile->write($contents, $mode); } catch (FileSystem_File_Exception $e) { throw new Cache_WriteException('Impossível escrever no arquivo de cache em ' . $path); } } /** * @see Cache_Facade_Abstract::remove() */ public function remove($directory, $fileName) { if(!self::exists($directory, $fileName)) { return true; } $file = $this->_getFile($directory, $fileName); return $file->delete(); } /** * @see Cache_Facade_Abstract::exists() */ public function exists($directory, $fileName) { if(!FileSystem_Directory::isDir(self::getCacheDir().$directory)) { return false; } $dir = new FileSystem_Directory(self::getCacheDir().$directory); $path = $dir->getPath().$fileName. '.' . self::CACHE_EXTENSION; return Cache_File::isFile($path) && Cache_File::isReadable($path); } /** * @see Cache_Facade_Abstract::get() */ public function get($directory, $fileName) { if(!self::isCacheEnabled()) { throw new Cache_DisabledException('O cache foi desabilitado nesta aplicação!'); } if(!$this->exists($directory, $fileName)) { return null; } $file = $this->_getFile($directory, $fileName); if($file->isExpired()) { return null; } $contents = $file->read(); try { $ret = unserialize($contents); return $ret === false ? null : $ret; } catch (ErrorException $e) { return $contents; } } /** * Seta o diretório para os arquivos de cache. * * @param string $cacheDir : caminho absoluto para o diretório * ou relatiovo ao diretório padrão de cache da aplicação * @return Cache_Facade : fluent interface */ public function setCacheDir($cacheDir) { $cacheDir = (string) $cacheDir; // Caso seja um caminho realativo, deve ser relativo ao diretório padrão if(strpos($cacheDir, '/') !== 0) { $cacheDir = Core::getInstance()->getCacheDir() . $cacheDir; } $this->_cacheDir = $cacheDir; return $this; } /** * Retorna o diretório de cache. * * @return string */ public function getCacheDir() { // Se não há um diretório de cache setado, usamos o padrão if($this->_cacheDir === null) { $this->_cacheDir = Core::getInstance()->getCacheDir(); } return $this->_cacheDir; } /** * Retorna uma instância de Cache_File com base no diretório e nome informados. * * @param string $directory : o subdiretório do arquivo * @param string $fileName : o nome do arquivo * @return Cache_File */ private function _getFile($directory, $fileName) { $dir = new FileSystem_Directory($this->getCacheDir().$directory); $path = $dir->getPath().$fileName. '.' . self::CACHE_EXTENSION; return new Cache_File($path); } } Valeu! Compartilhar este post Link para o post Compartilhar em outros sites
brcontainer 16 Denunciar post Postado Novembro 16, 2012 Invalidar que você se refere na área administrativa é "expirar" ou ao "editar" o cache você regravaria ele e tornaria disponível aos usuários a versão atualizada? O que eu entendo que você precisa é de uma automatização? Ou estou enganado? Por exemplo se o administrador editar a página de busca: http://site.com/busca/ invalidaria todas as páginas em cache geradas a partir dela? Por exemplo: http://site.com/busca/?q=termo 1 http://site.com/busca/?q=termo 2 http://site.com/busca/?q=termo 3 http://site.com/busca/?q=termo 3&orde=asc É isso? Compartilhar este post Link para o post Compartilhar em outros sites
Henrique Barcelos 290 Denunciar post Postado Dezembro 2, 2012 Exato... Eu não queria ter que fazer isso manualmente, pois planejo utilizar muito cache, acabaria ficando complicado. Compartilhar este post Link para o post Compartilhar em outros sites