<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Felipe Ribeiro &#187; apache</title>
	<atom:link href="http://blog.feliperibeiro.com/category/apache/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.feliperibeiro.com</link>
	<description>My hacks, slides and random stuff</description>
	<lastBuildDate>Fri, 05 Mar 2010 19:04:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Caching em PHP com uma técnica &#8220;obscura&#8221; mas muito eficiente</title>
		<link>http://blog.feliperibeiro.com/2008/12/caching-em-php-com-uma-tecnica-obscura-mas-muito-eficiente.html</link>
		<comments>http://blog.feliperibeiro.com/2008/12/caching-em-php-com-uma-tecnica-obscura-mas-muito-eficiente.html#comments</comments>
		<pubDate>Thu, 25 Dec 2008 17:29:41 +0000</pubDate>
		<dc:creator>Felipe Ribeiro</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web 2.0]]></category>

		<guid isPermaLink="false">http://blog.feliperibeiro.com/2008/12/caching-em-php-com-uma-tecnica-obscura-mas-muito-eficiente.html</guid>
		<description><![CDATA[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&#8230; Mas essa é a &#8220;maneira Rasmus Lerdorf&#8221; de se fazer cache com PHP sem nenhuma ferramenta externa e com uma sacada [...]]]></description>
			<content:encoded><![CDATA[<p style="clear: both">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&#8230;</p>
<p style="clear: both">Mas essa é a &#8220;<a title="Rasmus' trick" href="http://derickrethans.nl/errorhandling/rasmus-trick.html">maneira Rasmus Lerdorf</a>&#8221; de se fazer cache com PHP sem nenhuma ferramenta externa e com uma sacada fenomenal.</p>
<p style="clear: both">Para um servidor Web é <strong>muito</strong> 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.</p>
<p style="clear: both">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:</p>
<p style="clear: both">http://meusite.com.br/noticias/000001.html</p>
<p style="clear: both">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:</p>
<pre><code>
ErrorDocument 404 /noticias/gera_cache.php
</code></pre>
<p style="clear: both">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:</p>
<pre name="code" class="php:colapse:firstline[1]">

&lt;?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);
?&gt;
</pre>
<p style="clear: both">Sendo assim, o que vai acontecer:</p>
<p style="clear: both">Quando o usuário acessar pela primeira vez o link <strong>http://meusite.com.br/noticias/000001.html</strong>, o arquivo <strong>/noticias/000001.html</strong> não existirá e o usuário será redirecionado para o <strong>gera_cache.php</strong>. O <strong>gera_cache.php</strong> 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 <strong>http://meusite.com.br/noticias/000001.html</strong> o arquivo existirá e não passará mais pelo PHP.</p>
<p>É uma técnica bem &#8220;<strong>tricky</strong>&#8221; 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 <a href="http://br2.php.net/filectime">filectime</a> 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>
<p>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 <a href="http://pear.php.net/account-info.php?handle=ssb">Stig Bakken</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feliperibeiro.com/2008/12/caching-em-php-com-uma-tecnica-obscura-mas-muito-eficiente.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Algoritmo de &#8220;Você quis dizer&#8221;</title>
		<link>http://blog.feliperibeiro.com/2008/10/algoritmo-de-voce-quis-dizer.html</link>
		<comments>http://blog.feliperibeiro.com/2008/10/algoritmo-de-voce-quis-dizer.html#comments</comments>
		<pubDate>Wed, 08 Oct 2008 17:09:44 +0000</pubDate>
		<dc:creator>Felipe Ribeiro</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[desenvolvimento de software]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[web 2.0]]></category>
		<category><![CDATA[algoritmo]]></category>
		<category><![CDATA[busca]]></category>

		<guid isPermaLink="false">http://blog.feliperibeiro.com/?p=126</guid>
		<description><![CDATA[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. [...]]]></description>
			<content:encoded><![CDATA[<p>Recentemente precisei implementar um sistema de correção ortográfica à la Google.</p>
<p>Pesquisei bastante sobre como fazer isso, e encontrei duas maneiras que explicarei agora, mas antes disso explicarei algo que é comum às duas: <strong>A criação do dicionário</strong></p>
<p>Para criar o dicionário, você precisa ter uma base de palavras, que idealmente é um arquivo txt.</p>
<p>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.</p>
<pre name='code' class='php'>
&lt;?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));
?&gt;
</pre>
<p>1 &#8211; Algoritmo de Levenshtein</p>
<p>PHP implementa nativamente o algoritmo de Levenshtein (<a href="http://php.net/levenshtein">http://php.net/levenshtein</a>), que calcula a distância de edição entre duas palavras, funcionando da seguinte forma:</p>
<ul>
<li>suponha que eu tenha duas palavras: água e mágua &#8211;  A distância de edição delas é de uma inserção de carácter</li>
<li>suponha que eu tenha as palavras: casa e caixa &#8211; A distância delas é de uma substituição (s por i) e uma inserção (x)</li>
<li>suponha que eu tenha as palavras: arrocho e arroto &#8211; A distância delas é de uma substituição e uma remoção.</li>
</ul>
<p>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:</p>
<pre name='code' class='php'>
&lt;?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;
}
?&gt;
</pre>
<p>Análise de desempenho:</p>
<p>Considerando que temos <strong>k</strong> palavras no dicionário, a palavra que desejamos procurar tem <strong>m</strong> letras e cada palavra do dicionário tem em média <strong>n</strong> letras, o algoritmo de Levenshtein tem ordem de complexidade <strong>O(m*n)</strong> onde para <strong>k</strong> comparações (no caso da palavra <strong>não</strong> existir no dicionário, já que se ela existir não teremos nenhuma comparação) teremos <strong>O(k*m*n)</strong> (<strong>k*m*n</strong> operações onde <strong>k</strong> é muito maior que <strong>m</strong> e <strong>n</strong>).</p>
<p>2 - Algoritmo de Peter Norvig</p>
<p>Toda explicação probabilística desse algorítmo está presente no site do Norvig, um cara renomado na área de inteligência artificial: <a href="http://norvig.com/spell-correct.html">http://norvig.com/spell-correct.html</a>. 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).</p>
<p>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 (<a href="http://www.phpclasses.org/browse/file/24605.html">http://www.phpclasses.org/browse/file/24605.html</a>) e tenho recebido elogios e feedback muito positivo de quem está usando.</p>
<p>Análise de desempenho:</p>
<p>Considerando <strong>26</strong> letras do alfabeto (depois da reforma da língua portuguesa, agora também temos 26 letras! <img src='http://blog.feliperibeiro.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ) e considerando que sua palavra tem <strong>m</strong> 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 <strong>26*m</strong> 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 é <strong>O(1)</strong> então desprezaremos na análise de performance.</p>
<p>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.</p>
<p>Espero ter ajudado!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feliperibeiro.com/2008/10/algoritmo-de-voce-quis-dizer.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Analogias</title>
		<link>http://blog.feliperibeiro.com/2008/07/analogias.html</link>
		<comments>http://blog.feliperibeiro.com/2008/07/analogias.html#comments</comments>
		<pubDate>Wed, 16 Jul 2008 19:43:14 +0000</pubDate>
		<dc:creator>Felipe Ribeiro</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[funny]]></category>
		<category><![CDATA[geeky]]></category>
		<category><![CDATA[comics]]></category>

		<guid isPermaLink="false">http://blog.feliperibeiro.com/?p=94</guid>
		<description><![CDATA[Só para tirar as teias de aranha enquanto não tenho tempo de escrever nada.]]></description>
			<content:encoded><![CDATA[<p>Só para tirar as teias de aranha enquanto não tenho tempo de escrever nada.</p>
<p><a href="http://blog.feliperibeiro.com/wp-content/uploads/2008/07/analogies.png"><img class="aligncenter size-full wp-image-95" title="analogies" src="http://blog.feliperibeiro.com/wp-content/uploads/2008/07/analogies.png" alt="" width="500" height="450" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feliperibeiro.com/2008/07/analogias.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cheat sheets</title>
		<link>http://blog.feliperibeiro.com/2008/02/cheat-sheets.html</link>
		<comments>http://blog.feliperibeiro.com/2008/02/cheat-sheets.html#comments</comments>
		<pubDate>Sat, 16 Feb 2008 21:54:00 +0000</pubDate>
		<dc:creator>Felipe Ribeiro</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[desenvolvimento de software]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.feliperibeiro.com/blog/?p=79</guid>
		<description><![CDATA[&#8220;Quem cola não sai da escola&#8221;, é o ditado que a gente escuta no colégio, mas Cheat sheets e guias de bolso realmente são muito úteis quando você quer o nome daquela funçãozinha que faz exatamente o que você quer e você não lembra no momento, para consultas rápidas e não pra quem quer realmente [...]]]></description>
			<content:encoded><![CDATA[<p>&#8220;Quem cola não sai da escola&#8221;, é o ditado que a gente escuta no colégio, mas Cheat sheets e guias de bolso realmente são muito úteis quando você quer o nome daquela funçãozinha que faz exatamente o que você quer e você não lembra no momento, para consultas rápidas e não pra quem quer realmente aprender algo.<br />
Achei algumas bem interessantes e vou compartilhar aqui até para facilitar de me lembrar depois (uma Cheat sheet de cheat sheets <img src='http://blog.feliperibeiro.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> ):</p>
<ul>
<li><a href="http://ruby.cenophobie.com/RubyCheat.pdf">Ruby Cheat sheet</a></li>
<li><a href="http://www.scottklarr.com/topic/107/apache-cheat-sheets/">Apache Cheat sheets</a></li>
<li><a href="http://www.scottklarr.com/topic/102/mysql-cheat-sheets/">MySQL Cheat sheets</a></li>
<li><a href="http://www.scottklarr.com/topic/100/php-cheat-sheets/">PHP Cheat sheets</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.feliperibeiro.com/2008/02/cheat-sheets.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>O Mantra das REGEX &#8211; As 8 Expressões Regulares que precisamos saber.</title>
		<link>http://blog.feliperibeiro.com/2008/01/o-mantra-das-regex-as-8-expressoes-regulares-que-precisamos-saber.html</link>
		<comments>http://blog.feliperibeiro.com/2008/01/o-mantra-das-regex-as-8-expressoes-regulares-que-precisamos-saber.html#comments</comments>
		<pubDate>Wed, 30 Jan 2008 03:15:00 +0000</pubDate>
		<dc:creator>Felipe Ribeiro</dc:creator>
				<category><![CDATA[apache]]></category>
		<category><![CDATA[desenvolvimento de software]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[regex]]></category>

		<guid isPermaLink="false">http://www.feliperibeiro.com/blog/?p=77</guid>
		<description><![CDATA[Você tem medo de REGEX!? Eu também! Nos últimos tempos tenho lidado bastante com REGEX editando regras do Apache mod_rewrite e com a classe que publiquei no PHPClasses, a SiteMapGenerator Tabajara, que se propõe a gerar um mapa do site em xml no padrão estabelecido pelo Google para melhorar a indexação. Mas depois de tirar [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://feliperibeiro.com/imagens/fts-regex-front.jpg" alt="Regex" align="left" border="1" hspace="4" vspace="1" />Você tem <strong>medo</strong> de REGEX!? Eu também!</p>
<p>Nos últimos tempos tenho lidado bastante com REGEX editando regras do Apache mod_rewrite e com a classe que publiquei no PHPClasses, a <a href="http://www.phpclasses.org/browse/package/4305.html">SiteMapGenerator</a> <s>Tabajara</s>, que se propõe a gerar um mapa do site em xml no padrão estabelecido pelo Google para melhorar a indexação.</p>
<p>Mas depois de tirar onda da galera do Perl no post anterior, vou exaltar a importância que expressões regulares têm nas nossas validações, e para isso vou citar as 8 expressões regulares que todo programador Web deveria saber (exemplos em PHP, mas são válidos para qualquer linguagem com suporte a PCRE).</p>
<h4>Validação de nomes de usuário</h4>
<p>4 a 28 caracteres alfanuméricos e underscores:</p>
<p><code><br />
$string = "userNaME4234432_";<br />
if (preg_match('/^[a-z\d_]{4,28}$/i', $string)) {<br />
echo "exemplo 1 ok.";<br />
}<br />
</code></p>
<h4>Validação de números de telefone</h4>
<p><strong>(##) ####-####</strong> ou <strong>##-####-####</strong><br />
<code><br />
$string = "(32) 5555-5555";<br />
if (preg_match('/^(\(?[0-9]{2}\)?|[-. ]?)[ ][0-9]{4}[-. ]?[0-9]{4}$/', $string)) {<br />
echo "exemplo 2 ok.";<br />
}</code></p>
<p><code></code><span class="Apple-style-span" style="font-family: Courier; font-size: 13px"><br />
</span></p>
<h4>Endereços de e-mail</h4>
<p><strong>foo@bar.foo</strong><br />
<code><br />
$string = "first.last@domain.co.uk";<br />
if (preg_match('/^[^0-9][a-zA-Z0-9_]+([.][a-zA-Z0-9_]+)*[@][a-zA-Z0-9_]+([.]</code></p>
<p><code>[a-zA-Z0-9_]+)*[.][a-zA-Z]{2,4}$/',<br />
$string)) {<br />
echo "examplo 3 ok.";<br />
}<br />
</code></p>
<h4>CEPs</h4>
<p>#####-### ou ########</p>
<p><code>$string = "55324-432";<br />
if (preg_match('/^[0-9]{5,5}([- ]?[0-9]{4})?$/', $string)) {<br />
echo "exemplo 4 ok.";<br />
}</code></p>
<h4>Endereços IP</h4>
<p><strong>255.255.255.0</strong><br />
<code><br />
$string = "255.255.255.0";<br />
if (preg_match('^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:[.](?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$'</code></p>
<p><code>, $string)) {<br />
echo "exemplo 5 ok.";<br />
}</code></p>
<p><code><br />
</code></p>
<h4>Código de cores RGB em Hexadecimal</h4>
<p><strong>#FFFFFF, #FFF, FFF, FFFFFF</strong></p>
<p><code>$string = "#666666";<br />
if (preg_match('/^#(?:(?:[a-f\d]{3}){1,2})$/i', $string)) {<br />
echo "exemplo 6 ok.";<br />
}<br />
</code></p>
<h4>Comentários de múltiplas linhas</h4>
<p><strong>/* Lorem<br />
Ipsun<br />
dolor*/</strong><br />
<code><br />
$string = "/* commmmment */";<br />
if (preg_match('/^[(/*)+.+(*/)]$/', $string)) {<br />
echo "exemplo 7 ok.";<br />
}<br />
</code></p>
<h4>Datas</h4>
<p><strong>DD/MM/YYYY</strong> ou <strong>MM/DD/YYYY</strong><br />
<code><br />
$string = "30/01/2008";<br />
if (preg_match('/^\d{1,2}\/\d{1,2}\/\d{4}$/', $string)) {<br />
echo "exemplo 8 successful.";<br />
}<br />
</code><br />
Esses exemplos foram retirados do site Devolio[1] , porém algumas expressões eu alterei para ajustar aos padrões brasileiros de telefone e cep. Se por acaso fiz alguma besteira, peço que um <span class="Apple-style-span" style="font-weight: bold">REGEXPERT</span> comente e corrija! E no segundo link[2] um validador de expressões regulares.</p>
<p><a href="http://devolio.com/blog/archives/34-8-Practical-PHP-Regular-Expressions.html">[1] 8 Practical PHP Regular Expressions &#8211; Devolio</a><br />
<a href="http://www.devolio.com/regextester/">[2] Perl Compatible Regular Expression Tester</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.feliperibeiro.com/2008/01/o-mantra-das-regex-as-8-expressoes-regulares-que-precisamos-saber.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
