Caching é fundamental para a escalabilidade de aplicações Web. Existem diversas ferramentas que oferecem diferentes maneiras de se fazer isso, seja no Smarty, no APC, nos diversos frameworks, ou Memcached para os mais drásticos…
Mas essa é a “maneira Rasmus Lerdorf” de se fazer cache com PHP sem nenhuma ferramenta externa e com uma sacada fenomenal.
Para um servidor Web é muito mais rápido servir arquivos estáticos do que esperar que aquele arquivo seja interpretado por algum módulo ou que seja executado em CGI, e é isso o que esse método faz, gera arquivos estáticos sob demanda, utilizando os recursos que o Apache oferece.
Agora imagine que você tem um site de notícias e quer que elas sejam tratadas como arquivos estáticos, e os links para cada notícia seriam algo como:
http://meusite.com.br/noticias/000001.html
1º passo: Setamos nas configurações do Apache para que a página de erro 404 seja um arquivo .php (isso pode ser feito no .htaccess da pasta ou nas configurações do Apache propriamente dito). No caso do .htaccess, basta colocar isso:
ErrorDocument 404 /noticias/gera_cache.php
2º passo: Criamos o arquivo gera_cache.php, que irá tratar as requisições que teriam como resposta o erro 404 (Not Found) com o seguinte codigo:
<?php
$id = basename($_SERVER['REDIRECT_URL'], '.html');
/* Acessa a página dinâmica */
$html = file_get_contents(sprintf("http://meusite.com.br/noticias.php?id=%d",$id));
/* O ideal é fazer algum tratamento de erros, para evitar a criação de arquivos para ids inválidos */
/* Exibe o conteúdo */
header(sprintf('%s 200', $_SERVER['SERVER_PROTOCOL']));
echo $html;
/* Salva o conteúdo em um arquivo .html */
$fp = fopen(sprintf(dirname(__FILE__)."/%d.html", $id), "w");
fputs($fp, $html);
fclose($fp);
?>
Sendo assim, o que vai acontecer:
Quando o usuário acessar pela primeira vez o link http://meusite.com.br/noticias/000001.html, o arquivo /noticias/000001.html não existirá e o usuário será redirecionado para o gera_cache.php. O gera_cache.php acessa a página dinâmica que exibe o conteúdo da página com o id passado (000001) e salva em um html. Nos acessos consecutivos ao http://meusite.com.br/noticias/000001.html o arquivo existirá e não passará mais pelo PHP.
É uma técnica bem “tricky” e que precisa de cuidados. Por exemplo, você precisa ter uma rotina que expira os arquivos em cache após algum tempo e quando houver alguma alteração em determinada informação que interfere na página que está em cache, para garantir consistência dos dados. Uma maneira muito simples de se fazer isso é usando a função filectime do PHP para checar a idade dos arquivos em uma rotina que rodaria em background e apagaria os que fossem mais velhos que o tempo desejado. Mas funciona muito bem!
P.S.: Um artigo que li dizia que apesar de essa técnica ter se tornado pública através do Rasmus, ela foi criada mesmo pelo Stig Bakken.