Caching em PHP com uma técnica “obscura” mas muito eficiente 5

Posted by Felipe Ribeiro on December 25, 2008

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 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 seria 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 dessa técnica ter se tornado pública através do Rasmus, ela foi criada mesmo pelo Stig Bakken

Reportagem do Jornal da Globo sobre falha no IE 1

Posted by Felipe Ribeiro on December 18, 2008


Slides - PHP não é coisa de moleque 2

Posted by Felipe Ribeiro on December 05, 2008

Seguem os slides da miha apresentação no I Encontro de desenvolvedores PHP da Paraíba.

PHP não é coisa de moleque

View SlideShare presentation or Upload your own. (tags: php evangelizacao)

Os outros slides das palestras podem ser vistos aqui:

http://www.slideshare.net/tag/i-encontro-php-pb

Boas notícias

Posted by Felipe Ribeiro on December 01, 2008

Apesar do cansaço e da falta de tempo pra tudo, começo a semana muito alegre com duas coisas que aconteceram:

  • O encontro do PHP-Paraíba foi um SUCESSO! Parabéns a todos que organizaram!
  • Sou o vencedor do Innovation Award de Outubro no PHPClasses.org! Parabéns para mim!

Enfim, estou muito ocupado e volto a postar em breve! :-)

Comecei a me preparar pra prova de ZCE! 1

Posted by Felipe Ribeiro on November 09, 2008

Faz tempo que venho falando que vou fazer a prova, quando o dólar estava baixo eu deixei passar, e agora as coisas complicaram… Mas mesmo assim estou decidido a fazer no máximo em Janeiro.

Meu amigo Marcelo Schmidt, me “doou” os simulados que ele não precisou mais fazer quando tirou a certificação dele.

E hoje eu fiz um só pra ver como está o meu nível e foi melhor do que eu esperava! No guia de certificaçao só li até metade do capítulo “String and Patterns”, então já esperava me dar mal em coisas como Streams, que nunca mexi de verdade, só leitura e escrita simples em arquivos, e em segurança que tenho conhecimentos gerais mas não específicos de configuração do PHP. Mas enfim… estou bem satisfeito com o resultado, vou dar uma lida no que não me dei tão bem pra no próximo simulado conseguir tudo “excelent” e marcar a prova! :)

Oportunidade - Programador de Interfaces

Posted by Felipe Ribeiro on October 24, 2008

A startup que trabalho (shoprizer.com) tem uma equipe formada por Jedis (onde eu sou o Mestre Yoda :-D), que trabalham com PHP Hardcore e está precisando agora de um NINJA, um programador de interfaces, para trabalho remoto. Os requisitos são:

  • XHTML, CSS, Web standards
  • Javascript/AJAX
  • PHP básico/intermediário - só o necessário para a integração da lógica existente com a interface a ser feita.
  • Smarty
  • Disponibilidade de 20 horas semanais - flexíveis.
  • Inglês básico para leitura e escrita
  • Conhecimento de princípios de Usabilidade
  • Precisa ter o espírito de startup!

Se você está interessado, mande seu CV com links do seu portfolio para van2br@yahoo.com, atenção à Vanessa.

Review e slides do CONAPHP 3

Posted by Felipe Ribeiro on October 22, 2008

No último fim de semana (18 e 19 de outubro) houve em São Paulo o CONAPHP (www.conaphp.com.br), um evento feito pela comunidade PHP e que rolou dentro do CONISLI na FIAP.

O evento em geral foi bom, com bom nível de palestras mas o público foi um pouco abaixo do que eu esperava.

Para mim, o ponto alto foi quando estava assistindo a palestra do Elton Minetto (slides aqui) e “reconheci” um slide sobre o compilador JIT e o cache do opcode do PHP, um slide que fazia parte da apresentação que fiz em Recife no Encontro Pernambucano de SL, e para confirmar vi lá meu link nas referências, e isso me deixou bastante honrado por ter um material meu usado como referência por um ícone como o Elton.

A minha palestra foi a última e falei sobre PHP RESTful Web Services, por ser a última, o título não ser apelativo para o pessoal mais iniciante e eu ser um ilustre desconhecido da comunidade PHP de São Paulo, tive apenas metade da sala cheia, mas o feedback das pessoas que assitiram a palestra foi bastante positivo e fiquei muito satisfeito.

Os slides da palestra seguem abaixo, e o código apresentado está disponível aqui.

PHP RESTful Web Services

View SlideShare presentation or Upload your own. (tags: php rest)

Quem tiver interesse sobre o assunto, deixo algumas referências:

Algoritmo de “Você quis dizer”

Posted by Felipe Ribeiro on October 08, 2008

Recentemente precisei implementar um sistema de correção ortográfica à la Google.

Pesquisei bastante sobre como fazer isso, e encontrei duas maneiras que explicarei agora, mas antes disso explicarei algo que é comum às duas: A criação do dicionário

Para criar o dicionário, você precisa ter uma base de palavras, que idealmente é um arquivo txt.

Você lê o arquivo e cria um array onde as palavras são as chaves e as frequências com que aparecem nos textos serão os valores.

<?php
$text
= file_get_contents(‘arquivo.txt’);
preg_match_all(“/[a-z]+/”,strtolower($text),$matches);
$palavras = $matches[0];
$dicionario
= array();
foreach(
$palavras as $palavra)
$dicionario[$palavra] += 1;
sort($dicionario); /* Essa ordenação será útil para otimização de performance no primeiro algoritmo */ file_put_contents(‘dicionario_serializado.dat’,serialize($dicionario);
?>

1 - Algoritmo de Levenshtein

PHP implementa nativamente o algoritmo de Levenshtein (http://php.net/levenshtein), que calcula a distância de edição entre duas palavras, funcionando da seguinte forma:

  • suponha que eu tenha duas palavras: água e mágua - A distância de edição delas é de uma inserção de carácter
  • suponha que eu tenha as palavras: casa e caixa - A distância delas é de uma substituição (s por i) e uma inserção (x)
  • suponha que eu tenha as palavras: arrocho e arroto - A distância delas é de uma substituição e uma remoção.

A função levenshtein também permite que você dê pesos diferenciados para inserção/remoção/substituição, sendo que o valor default é 1 para todas operações. Usando essa função, fica simples implementar um corretor, supondo que você tem um dicionário que já citei, você só precisa fazer:

<?php
function
voce_quis_dizer($palavra_procurada) {
$dicionario
= unserialize(file_get_contents(‘dicionario_serializado.dat’)); $minima_distancia = -1;
$palavra_procurada
= strtolower($palavra_procurada);
foreach(
$dicionario as $palavra_do_dicionario) {
if(
$palavra_procurada == $palavra_do_dicionario) return $palavra;
$distancia = levenshtein($palavra_procurada,$palavra_do_dicionario);
if(
$distancia < $minima_distancia || $minima_distancia == -1) {
$minima_distancia = $distancia;
$sugestao = $palavra_do_dicionario;
}
}
return
$sugestao;
}
?>

Análise de desempenho:

Considerando que temos k palavras no dicionário, a palavra que desejamos procurar tem m letras e cada palavra do dicionário tem em média n letras, o algoritmo de Levenshtein tem ordem de complexidade O(m*n) onde para k comparações (no caso da palavra não existir no dicionário, já que se ela existir não teremos nenhuma comparação) teremos O(k*m*n) (k*m*n operações onde k é muito maior que m e n).

2 - Algoritmo de Peter Norvig

Toda explicação probabilística desse algorítmo está presente no site do Norvig, um cara renomado na área de inteligência artificial: http://norvig.com/spell-correct.html. Mas basicamente esse algoritmo apesar de mais complicado é bem mais inteligente que o primeiro. O que ele faz é o seguinte: gera perturbações na sua palavra procurada e vê quais dessas perturbações é a mais relevante no dicionário. Evitando comparações desnecessárias, já que no primeiro algoritmo cada palavra que você colocar será comparada com todas as outras (por exemplo: se você digitar BOLA, e ela não existir no dicionário ela será comparada com palavras absurdas como: LIVRO, que obviamente não é o que você quis dizer).

Apesar do conceito do Norvig ser simples, o código é um pouquinho complicado. Então eu criei uma classe que implementa ele e disponibilizei sob Licença BSD no PHPClasses.org (http://www.phpclasses.org/browse/file/24605.html) e tenho recebido elogios e feedback muito positivo de quem está usando.

Análise de desempenho:

Considerando 26 letras do alfabeto (depois da reforma da língua portuguesa, agora também temos 26 letras! :D) e considerando que sua palavra tem m letras, teremos mais ou menos 26*m iterações para gerar as possíveis perturbações na palavra (inserções, remoções e substituições possíveis), e para garantir um segundo nível de perturbações teremos aproximadamente 26*m para cada perturbação gerada, que dá um total de aproximadamente (26*m)*(26*m) = 676 m². Agora só precisamos consultar cada uma das perturbações para vermos qual a mais relevante no dicionário. Cada consulta no dicionário é O(1) então desprezaremos na análise de performance.

E podemos considerar esse algoritmo como sendo mais eficiente do que o primeiro pois o tempo de execução cresce de acordo com o quadrado do tamanho da palavra (que normalmente é bem menor do que o tamanho do dicionário). Enquanto o primeiro sofre interferência do tamanho do dicionário e do tamanho médio das palavras contidas lá, então esse é bem mais inteligente e eficiente.

Espero ter ajudado!

Mais um termo para o Glossário Geek - “Ad hoc” 2

Posted by Felipe Ribeiro on September 15, 2008

No ambiente acadêmico tenho encontrado essa expressão em diversos lugares como:

  • Implementação MVC ad hoc
  • Processo de desenvolvimento ad hoc
  • Redes ad hoc

E acho que muitas pessoas não entendem o significado desse termo, e muitas vezes é pronunciado errado.

Ad hoc indica que algo é feito de maneira empírica, sem formalismo, por exemplo:

Uma implementação de MVC ad hoc, é uma implementação do padrão de projeto sem a utilização de nenhum framework para tal, algo “puro” feito de acordo com o seu entendimento sobre o padrão.

Um processo de desenvolvimento ad hoc é um processo em que as coisas rolam sem nenhum formalismo bem definido, e por aí vai.

Algumas pessoas pronunciam esse termo como se fosse em inglês, como se fosse algo tipo “add hock”, mas o correto é da maneira como lemos em português mesmo, já que é um termo em latin, se pronuncia o A com som de A mesmo, e o H é mudo, como se fosse: adoque.

Esse post pode parecer inútil, mas espero que sirva para alguém que tem a dúvida do que significa e como se pronuncia, já que é fácil encontrar na literatura ou ouvir alguém falando, e também para tirar as teias de aranha do blog enquanto tomo um fôlego e arranjo uma brechinha na correria para voltar a postar.

Documentário - A verdadeira história da Internet: A guerra dos browsers 1

Posted by Felipe Ribeiro on September 08, 2008

O Discovery Channel vai apresentar uma série de documentários sobre a história da internet. Para nossa alegria o primeiro episódio, entitulado “A Guerra dos Browsers” foi disponibilizado oficialmente na internet:

Vale a pena assistir, é um vídeo super interessante que conta a história dos browsers, desde o Mosaic (bisavô do Firefox) até a briga judicial da infame Microsoft com seu ainda mais infame Internet Explorer e o Netscape (avô do Firefox). O vídeo tem cerca de 43 minutos, mas é muito interessante, recomendadíssimo! E tenho certeza que depois dele, se você ainda usa IEca, vai deixar de usar.