<?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>Ataraxia! &#187; programação</title>
	<atom:link href="http://www.ataraxia.com.br/posts/category/programacao/feed" rel="self" type="application/rss+xml" />
	<link>http://www.ataraxia.com.br</link>
	<description>O estado da arte em TI</description>
	<lastBuildDate>Thu, 26 Aug 2010 15:43:15 +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>Removendo o &#8220;generator&#8221; do WordPress</title>
		<link>http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress</link>
		<comments>http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress#comments</comments>
		<pubDate>Thu, 26 Aug 2010 15:43:15 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[dicas]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=375</guid>
		<description><![CDATA[Ok, dica rápida para os que não gostam do WordPress anunciando para o mundo a versão em suas tags meta. Normalmente, qualquer site em WordPress vai ter uma tag meta em seu header mais ou menos assim: &#60;meta name=&#34;generator&#34; content=&#34;WordPress 2.8.4&#34; /&#62; Muita gente não gosta de anunciar para o mundo a versão usada. Seja [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, dica rápida para os que não gostam do WordPress anunciando para o mundo a versão em suas tags meta. Normalmente, qualquer site em WordPress vai ter uma tag meta em seu header mais ou menos assim:</p>

<div class="wp_syntax"><div class="code"><pre class="xhtml" style="font-family:monospace;">&lt;meta name=&quot;generator&quot; content=&quot;WordPress 2.8.4&quot; /&gt;</pre></div></div>

<p>Muita gente não gosta de anunciar para o mundo a versão usada. Seja por não querer exibir o uso do WordPress, ou por medo de alguem usar essa informação para um possível ataque contra essa versão específica do WordPress, existe uma forma muito simples de retirar isso do cabeçalho, sem precisar editar os arquivos do sistema (que a priori, nunca devem ser editados).<br />
Essa tag é inserida no cabeçalho através de uma <em>action</em> padrão, chamada <strong>wp_generator</strong>. Para não exibir, basta remover a action, adicionando o seguinte código no functions.php do seu tema:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
remove_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wp_head'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'wp_generator'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Pronto, com isso o seu site não irá mais exibir esta tag no cabeçalho.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Escrevendo plugins para o WordPress</title>
		<link>http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress</link>
		<comments>http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress#comments</comments>
		<pubDate>Mon, 14 Sep 2009 04:39:52 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=347</guid>
		<description><![CDATA[O WordPress é um excelente sistema para blogs, feito em PHP. Além de ser bastante fácil de instalar e usar, existe um sem número de plugins já prontos e disponíveis para estender suas funcionalidades, e mais tantos temas que podem ser usados para dar &#8220;cara nova&#8221; ao blog. De fato, este blog que você está [...]]]></description>
			<content:encoded><![CDATA[<p>O <a href="http://wordpress.org/">WordPress</a> é um excelente sistema para blogs, feito em PHP. Além de ser bastante fácil de instalar e usar, existe um sem número de plugins já prontos e disponíveis para estender suas funcionalidades, e mais tantos temas que podem ser usados para dar &#8220;cara nova&#8221; ao blog. De fato, este blog que você está lendo neste momento também usa o WordPress!<br />
Os <a href="http://wordpress.org/extend/plugins">vários plugins disponíveis</a> adicionam todo tipo de funcionalidade nova ao sistema, seja um widget para mostrar os últimos tweets de alguém, links para posts relacionados, enfim&#8230; tudo é possível!<br />
Porém, volta e meia precisamos adicionar uma funcionalidade e não existe um plugin já pronto que sirva exatamente para o que queremos. Neste caso, uma opção é criar o nosso próprio plugin. A linguagem do WordPress é o PHP, e tendo alguma noção de como as coisas funcionam no WordPress, essa não é uma tarefa muito complexa.</p>
<h2>Criando um plugin</h2>
<p>Neste artigo, vamos mostrar o passo a passo da criação de um plugin simples, que visa guardar em uma tabela o número de visualizações de cada post do blog. Só isso. Não teremos gráficos, tabelas, nada do tipo. Apenas vamos guardar os dados, que podem ser utilizados por uma outra ferramenta qualquer.<br />
O objetivo não é apenas mostrar como se criar um plugin. A partir deste esqueleto, adicionar mais funcionalidades fica mais fácil.</p>
<h2>O cabeçalho do plugin</h2>
<p>Antes de mais nada, logo no início precisamos ter um cabeçalho no arquivo do plugin que informará ao WordPress algumas informações, como nome do plugin, uma descrição, autor, versão, e outras coisas. É importante ter isso bem definido.<br />
Essas informações entram em um comentário logo no início do arquivo. No nosso caso, teremos o seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">/*
Plugin Name: View Counter
Description: Increments a counter each time a post is viewed
Version: 1.0
Author: Bruno Lustosa
Author URI: http://www.ataraxia.com.br/
*/</span></pre></div></div>

<p>Pronto, já temos aí o nome do plugin (View Counter), uma breve descrição do que ele faz, a versão, o nome do autor e a URL do autor, para referência. O WordPress exibe essas informações na página dos plugins na área administrativa. Coloquei as informações em inglês, pois a interface administrativa deste blog está toda em inglês.</p>
<h2>Os hooks</h2>
<p>Entenda os hooks como ações onde você pode criar um callback. Ou seja, sempre que determinada ação for executada no WordPress, uma função definida por você será chamada. No nosso caso, vou definir 2 hooks e uma ação (a ação é parecida com o hook, mostrarei a diferença logo abaixo).</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Hooks</span>
register_activation_hook<span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;viewcounter_activate&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
register_deactivation_hook<span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;viewcounter_deactivate&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
add_action<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'save_post'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'viewcounter_insert'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>O primeiro hook determina que a função <em>viewcounter_activate()</em> será executada quando o plugin for ativado. Esta função cuidará da criação da tabela, caso necessário. Da mesma forma, o segundo hook executará <em>viewcounter_deactivate()</em>, que destruirá nossa tabela, para deixar o sistema limpo como estava antes da ativação. É sempre uma boa prática remover o que criamos após a desinstalação.<br />
A ação é bem semelhante ao hook, e no caso, executará a função <em>viewcounter_insert()</em> assim que um post for salvo. Esta função irá inserir uma linha em nossa tabela, definindo o número de leituras como sendo zero.</p>
<h2>Nossa tabela</h2>
<p>Iremos criar uma tabela bem simples para guardar as nossas informações. Tudo que precisaremos, é de um campo para guardar o ID do post, e outro pra guardar o número de visualizações. Sim, poderíamos alterar a tabela de posts e adicionar um campo com o número de visualizações, porém, prefiro não mexer em tabelas do sistema, para evitar problemas de compatibilidade futura (vai que uma versão futura do WordPress possui um campo com esse mesmo nome?).<br />
O comando para a criação da tabela:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> viewcounter <span style="color: #66cc66;">&#40;</span>
    post_ID INT <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span><span style="color: #66cc66;">,</span>
    views INT <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #cc66cc;">0</span>
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<h2>O hook de ativação</h2>
<p>Com a definição da nossa tabela em mãos, vamos partir para a função de ativação do plugin. Ela será executada uma única vez, quando o administrador ativar o plugin.<br />
Nossa função, por segurança, irá checar se a tabela que queremos criar já existe, para evitar erros. A checagem usará o comando SQL <em>SHOW TABLES</em>.<br />
A função ficará assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> viewcounter_activate<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">,</span> <span style="color: #000088;">$viewcounter_table</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get_var</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SHOW TABLES LIKE '<span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span>'&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000088;">$viewcounter_table</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span>
        <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;CREATE TABLE <span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span> (post_ID INT NOT NULL PRIMARY KEY, views INT NOT NULL DEFAULT 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// viewcounter_activate</span></pre></div></div>

<p>Note que temos duas variáveis globais. A primeira, <em>$wpdb</em>, é do próprio WordPress, e é usada para acessar o banco de dados e executar queries. A segunda, foi definida por nós, e contem o nome da tabela que usaremos. Lembra, que durante a instalação do WordPress, ele te pediu um prefixo para as tabelas? Ao invés de deixarmos um nome fixo, é sempre bom definir o nome da tabela usando este prefixo.<br />
Assim, esta segunda variável global foi definida fora da função, da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$viewcounter_table</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$viewcounter_table</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;<span style="color: #006699; font-weight: bold;">{$wpdb-&gt;prefix}</span>viewcounter&quot;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Resumindo, se você definiu o prefixo para as tabelas do WordPress como <em>wp_</em>, então nossa tabela se chamará <em>wp_viewcounter</em>. Isso é especialmente importante caso seu plugin seja usado em um sistema multi-usuário, como o <a href="http://mu.wordpress.org/">WordPress MU</a>.</p>
<h2>A desativação</h2>
<p>Bem semelhante à nossa função de ativação, temos a função que será executada quando o plugin for desativado. A idéia aqui é limpar tudo que fizemos, deixando o sistema como estava antes. Para tanto, basta destruir a nossa tabela.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> viewcounter_deactivate<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">,</span> <span style="color: #000088;">$viewcounter_table</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;DROP TABLE <span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// viewcounter_deactivate</span></pre></div></div>

<p>Simples assim. Desativou o plugin, destruiu a tabela.</p>
<h2>Quando salvamos o post</h2>
<p>Assim que um post é salvo, temos a função <em>viewcounter_insert()</em> que será chamada, tendo como parâmetro o ID do novo post. Esta função deve inserir uma linha em nossa tabela, indicando que esse novo post teve 0 visualizações até o momento, o que é lógico, pois ele acabou de ser criado.<br />
A função também fica bem simples:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> viewcounter_insert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$post_ID</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">,</span> <span style="color: #000088;">$viewcounter_table</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;INSERT INTO <span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span> (post_ID, views) VALUES (<span style="color: #006699; font-weight: bold;">{$post_ID}</span>, 0)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// viewcounter_insert</span></pre></div></div>

<h2>A contagem propriamente dita</h2>
<p>E por último, temos a contagem das visualizações. Para tanto, teremos uma função chamada <em>viewcounter_update()</em>, que receberá como parâmetro o ID do post a ser atualizado. Para conveniência, essa função também irá retornar o número atualizado de visualizações que o post teve, que poderá ser usado no template em algum lugar.<br />
Esta função tem algumas checagens extras que são feitas por segurança. Por exemplo, caso um post antigo seja visualizado, precisaremos rodar a função que cria a linha para o post, pois como ele foi criado antes da ativação do plugin, o hook anterior não foi chamado.<br />
A função pode ficar assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> viewcounter_update<span style="color: #009900;">&#40;</span><span style="color: #000088;">$post_ID</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">global</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">,</span> <span style="color: #000088;">$viewcounter_table</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get_var</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT views FROM <span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span> WHERE post_ID = <span style="color: #006699; font-weight: bold;">{$post_ID}</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span>
        viewcounter_insert<span style="color: #009900;">&#40;</span><span style="color: #000088;">$post_ID</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">query</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;UPDATE <span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span> SET views = views + 1 WHERE post_ID = <span style="color: #006699; font-weight: bold;">{$post_ID}</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$wpdb</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get_var</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT views FROM <span style="color: #006699; font-weight: bold;">{$viewcounter_table}</span> WHERE post_ID = <span style="color: #006699; font-weight: bold;">{$post_ID}</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span> <span style="color: #666666; font-style: italic;">// viewcounter_update</span></pre></div></div>

<p>A primeira query checa se o retorno é vazio, e caso seja, chama a função viewcounter_insert() para inserir uma linha com 0 visualizações. Em seguida, executa um <em>update</em> incrementando em 1 o número de visualizações. E por último, retorna o número atual de visualizações do post.</p>
<h2>Atualizando</h2>
<p>Tudo que faltou agora, é indicar o ponto onde viewcounter_update() deve ser chamada. Na <a href="http://codex.wordpress.org/Template_Hierarchy">hierarquia dos templates</a>, o ponto ideal para colocarmos nossa chamada é no arquivo <em>single.php</em>.<br />
Bastaria uma simples chamada como:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$num</span> <span style="color: #339933;">=</span> viewcounter_update<span style="color: #009900;">&#40;</span><span style="color: #000088;">$post</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">ID</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>E já teríamos o banco atualizado (claro, supondo que temos em $post o objeto com o post). Caso queiramos exibir o número atual de visualizações, podemos utilizar a variável $num em qualquer ponto do template para mostrar ao usuário quantas vezes aquele post foi visto.</p>
<h2>Conclusão</h2>
<p>Este foi apenas um exemplo, bem tosco, de como criar um template para o WordPress. É claro que ele pode ser melhorado, e muito. Inclusive, aceito sugestões nos comentários.<br />
Estou disponibilizando um <a href="http://www.ataraxia.com.br/wp-content/uploads/2009/09/viewcounter.zip">arquivo com este plugin</a>, para quem quiser baixar e experimentar.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Otimização de sites com memcached</title>
		<link>http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached</link>
		<comments>http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached#comments</comments>
		<pubDate>Sat, 16 May 2009 16:01:32 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[bd]]></category>
		<category><![CDATA[memoria]]></category>
		<category><![CDATA[otimização]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=328</guid>
		<description><![CDATA[Um projeto muito interessante, e que pode ser usado pra aumentar drasticamente o desempenho de aplicativos web é o Memcached. Pela descrição do site do projeto, o &#8220;memcached é um sistema distribuído de alto desempenho para o cacheamento de objetos na memória, genérico por natureza, mas feito para se aumentar a velocidade de sites dinâmicos [...]]]></description>
			<content:encoded><![CDATA[<p>Um projeto muito interessante, e que pode ser usado pra aumentar drasticamente o desempenho de aplicativos web é o <a href="http://www.danga.com/memcached/">Memcached</a>. Pela descrição do site do projeto, o &#8220;memcached é um sistema distribuído de alto desempenho para o <i>cacheamento</i> de objetos na memória, genérico por natureza, mas feito para se aumentar a velocidade de sites dinâmicos diminuindo a carga no banco de dados&#8221;.<br />
O memcached funciona como um grande dicionário, que armazena tuplas do tipo [chave, valor]. Para armazenar um objeto qualquer, basta conectar no memcached e passar uma chave para acessá-lo e o objeto (e opcionalmente outros parâmetros, como tempo de armazenamento). Para buscar o objeto, basta conectar ao memcached e pedir a ele o objeto que possui a chave previamente criada.<br />
Digamos que uma página web precise fazer algumas consultas pesadas em um banco de dados. A idéia é justamente pegar o resultado da consulta e jogar pra dentro do memcached. Na próxima vez que a consulta precisar ser feita, o programa irá primeiro checar se o resultado já está disponível no memcached. Se estiver, ótimo, economizamos uma query pesada. Se não estiver, o programa faz a consulta e guarda o resultado no memcached. Simples assim!</p>
<h2>Exemplo em PHP</h2>
<p>O memcached pode ser acessado de muitas linguagens de alto nível, como C/C++, Java, Python, PHP, e até .NET. Abaixo, um exemplo em PHP.<br />
Antes do memcache, uma página poderia ter uma consulta do seguinte tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// A query SQL está abreviada, apenas como exemplo</span>
<span style="color: #666666; font-style: italic;">// Digamos que essa consulte demore cerca de 1 segundo</span>
<span style="color: #666666; font-style: italic;">// para ser completada</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM tabela INNER JOIN ......&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #990000;">pg_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$arr</span> <span style="color: #339933;">=</span> <span style="color: #990000;">pg_fetch_all</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// array com todos os resultados</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Com esse código, a cada acesso na página, teremos uma consulta de 1 segundo feita ao banco de dados. Muitas vezes, a consulta será exatamente a mesma. Modificando a consulta para uso do memcached, teríamos algo assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #666666; font-style: italic;">// Conecta ao memcached</span>
<span style="color: #000088;">$mc</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Memcache<span style="color: #339933;">;</span>
<span style="color: #000088;">$mc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addServer</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ip.do.servidor'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM tabela INNER JOIN ......&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$cache</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$mc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Usamos o md5() da query como chave</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$cache</span> <span style="color: #339933;">===</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Resultado não está no cache</span>
    <span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #990000;">pg_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$arr</span> <span style="color: #339933;">=</span> <span style="color: #990000;">pg_fetch_all</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$mc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$arr</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$arr</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$cache</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Pelo exemplo acima, temos algumas modificações. Primeiramente conectamos ao memcached. A chamada a addServer() pode ser feita múltiplas vezes, caso existam vários memcached rodando em máquinas separadas. Pode ser dado um &#8220;peso&#8221; pra cada servidor também, de acordo com a memória disponível em cada um.<br />
Logo em seguida, é feita a verificação no memcached se o resultado da consulta já está lá. Como chave, usei o hash md5 da consulta, pra gerar uma identificação única. O método get() pode retornar false, caso a chave não esteja no memcached, ou retornar o objeto que foi guardado.<br />
A checagem é simples. Se o get() retornou false, então o sistema faz a consulta como já fazia antes, e no fim guarda o resultado no memcached, pra agilizar as próximas consultas. E caso não tenha retornado false, temos já o resultado da consulta diretamente. Ao fim do bloco <i>if</i>, teremos, de uma forma ou de outra, o resultado da consulta em $arr.<br />
A diferença é que rodando a consulta no banco, o tempo será de cerca de 1 segundo (tempo que estimamos para a execução da consulta), e pegando o resultado direto do memcached, a consulta demorará algo da ordem de milissegundos para ser completada.</p>
<h2>Problemas</h2>
<p>Um dos problemas clássicos em qualquer abordagem que use cache é como saber se as informações em cache ainda estão atuais. Com o memcached, isso não é diferente. Existem algumas formas de se lidar com o problema.<br />
A primeira delas, mais simples, e que pode ser usada livremente caso não seja de suma importância que os dados estejam atuais, é mexer no tempo em que a informação ficará no cache. O tempo pode ser especificado na chamada ao método set(), da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$mc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$arr</span><span style="color: #339933;">,</span> MEMCACHE_COMPRESSED<span style="color: #339933;">,</span> <span style="color: #cc66cc;">60</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Temos neste exemplo todos os parâmetros para a chamada de set(): a chave, o objeto a ser guardado, uma flag (pode ser usado MEMCACHE_COMPRESSED, que indica que o objeto será comprimido para ocupar menos espaço, ou 0 pra indicar que deve ser guardado sem compressão), e por último o tempo de vida do objeto, no caso, 60 segundos.<br />
Ou seja, caso não haja problema das informações permanecerem desatualizadas por 60 segundos no máximo, essa abordagem pode ser usada.<br />
Caso a informação tenha que estar sempre atualizada, a forma de tratamento terá que ser outra. O memcached possui método para apagar o objeto associado a uma chave. Tendo a chave, basta usar:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$mc</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'chave'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>e a entrada que existia no memcached para aquela chave será invalidada.<br />
A idéia, nesse segundo caso, é justamente localizar no código todos os pontos que modificam o banco de dados de forma que possa alterar o resultado da consulta feita, e adicionar código para invalidar o cache nesses pontos. Assim, quando for feita a consulta no memcached, caso alguma informação tenha sido modificada, a entrada correspondente no memcached já terá sido apagada, e a chamada a get() retornará false naturalmente.<br />
É claro que essa segunda abordagem dá muito mais trabalho, por isso a sugestão de se usar a primeira delas nos casos em que pode ser usada. Lembre-se que em um site com 100 acessos por segundo, um tempo de vida de 60 segundos evitará 5999 consultas ao banco (a primeira será feita e guardada).</p>
<h2>Mais informações</h2>
<p>O site do projeto tem <a href="http://code.google.com/p/memcached/wiki/Start">um Wiki</a> que responde a maior parte das dúvidas que se pode ter, em relação a instalação e ao uso.<br />
No caso do PHP, as funções são bem documentadas na <a href="http://br.php.net/manual/en/book.memcache.php">parte do manual sobre memcache</a>.<br />
Eu uso em produção o memcached, com 2 servidores, um com 768mb de memória disponíveis para o memcached e outro com 256mb. Dei pesos 3 e 1 respectivamente, para que um objeto tenha 3 vezes mais chance de cair no primeiro servidor. A configuração está bastante satisfatória, e o banco de dados agradece.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-imagens-inline" title="Otimização: imagens inline">Otimização: imagens inline</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-parte-3-cache" title="Otimização de sites, parte 3 &#8211; Cache">Otimização de sites, parte 3 &#8211; Cache</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-parte-2-compressao" title="Otimização de sites, parte 2 &#8211; Compressão">Otimização de sites, parte 2 &#8211; Compressão</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/problemas-com-acentuacao" title="Problemas com acentuação?">Problemas com acentuação?</a></li><li><a href="http://www.ataraxia.com.br/posts/o-limite-de-4-ou-3-gb-de-memoria" title="O limite de 4 (ou 3?) Gb de memória">O limite de 4 (ou 3?) Gb de memória</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Evitando SQL injection em PHP</title>
		<link>http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php</link>
		<comments>http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php#comments</comments>
		<pubDate>Thu, 23 Apr 2009 00:13:09 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[segurança]]></category>
		<category><![CDATA[fieo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[validação]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=318</guid>
		<description><![CDATA[Em um mundo ideal, todos os desenvolvedores, ao programar seus aplicativos em qualquer linguagem, deveriam se preocupar com segurança, em especial com a validação dos dados. No PHP, isso não é diferente. Uma classe de problemas de segurança bem específica do ambiente web é a chamada SQL Injection, literalmente uma &#8220;Injeção de SQL&#8221;. E embora [...]]]></description>
			<content:encoded><![CDATA[<p>Em um mundo ideal, todos os desenvolvedores, ao programar seus aplicativos em qualquer linguagem, deveriam se preocupar com segurança, em especial com a <a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php">validação dos dados</a>. No PHP, isso não é diferente.<br />
Uma classe de problemas de segurança bem específica do ambiente web é a chamada <em>SQL Injection</em>, literalmente uma &#8220;Injeção de SQL&#8221;. E embora a solução seja simples, é preciso que o programador preste atenção, pra evitar que seu aplicativo acabe sendo explorado por uma falha de segurança como esta.</p>
<h2>O problema</h2>
<p>Digamos que na página principal do nosso site, a gente tenha um formulário de login mais ou menos assim:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">form</span> <span style="color: #000066;">action</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;login.php&quot;</span> <span style="color: #000066;">method</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;post&quot;</span>&gt;</span>
Login: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;login&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
Senha: <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;password&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;senha&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">form</span>&gt;</span></pre></div></div>

<p>Um formulário bem simples. E para tratar este formulário, temos o login.php, que vai checar em um banco de dados se o login e a senha estão corretos, da seguinte forma (colocarei apenas o trecho com a consulta SQL relevante):</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$sql</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;SELECT * FROM usuarios WHERE login = '<span style="color: #006699; font-weight: bold;">{$_POST['login']}</span>' AND senha = '<span style="color: #006699; font-weight: bold;">{$_POST['senha']}</span>'&quot;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$res</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_query</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">mysql_num_rows</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$res</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;Login OK&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;Login e senha não conferem&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Ou seja, verificamos na tabela <em>usuarios</em> se temos uma linha com o login e a senha fornecidos. Caso essa consulta retorne alguma coisa, significa que existe uma linha com o login e a senha fornecidos, caso contrário, não existe.<br />
Se no formulário eu preencho o login com &#8220;joe&#8221; e a senha com &#8220;xxxx&#8221;, a seguinte consulta SQL será montada e executada:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> usuarios <span style="color: #993333; font-weight: bold;">WHERE</span> login <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'joe'</span> <span style="color: #993333; font-weight: bold;">AND</span> senha <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'xxxx'</span></pre></div></div>

<p>Porém, o que acontece se eu preecher o formulário com o login = joe, e a senha com:  xxxx&#8217; OR true &#8211;<br />
Neste caso, teremos a seguinte consulta:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> usuarios <span style="color: #993333; font-weight: bold;">WHERE</span> login <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'joe'</span> <span style="color: #993333; font-weight: bold;">AND</span> senha <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'xxxx'</span> <span style="color: #993333; font-weight: bold;">OR</span> true <span style="color: #808080; font-style: italic;">--'</span></pre></div></div>

<p>Essa consulta vai retornar todas as linhas do banco de dados (por causa do &#8220;OR true&#8221; no final), e como a checagem no código é se a consulta retornou mais de uma linha, estaremos logados.<br />
Existem formas mais sofisticadas de proceder com este tipo de ataque, mas o foco do artigo é na defesa.</p>
<h2>FIEO</h2>
<p><acronym title="Filter Input/Escape Output">FIEO</acronym> é uma técnica bastante usada para aumentar a segurança dos aplicativos web. Significa &#8220;Filter Input/Escape Output&#8221;, ou traduzindo, &#8220;Filtre a Entrada/Escape a Saída&#8221;.<br />
O primeiro passo é a filtragem da entrada, já que a regra número 1 da segurança em aplicativos web diz que não podemos jamais confiar em informações vindas de fontes externas. No nosso caso, poderíamos fazer a filtragem do login e da senha checando se eles possuem apenas caracteres permitidos. Por exemplo, o site poderia ter uma regra especificando que o login deve conter apenas letras e números. A filtragem então, poderia ser feita usando a função <a href="http://br2.php.net/ctype_alnum">ctype_alnum()</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">ctype_alnum</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;login possúi caracteres inválidos&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Se o <em>FI</em> do FIEO lida com a filtragem da entrada, o <em>EO</em> lida com a manutenção da saída no contexto em que for lida.<br />
Ou seja, <em>FI</em> garante que a nossa entrada é valida, e <em>EO</em> garante que quem quer que receba os nossos dados, irá interpretá-los da forma correta.<br />
No nosso caso, é importante que as aspas simples não sejam interpretadas como delimitadores na consulta SQL. E se eu quisesse ter uma senha que tivesse uma aspa simples no meio?<br />
Existem 3 formas clássicas de se resolver este problema.</p>
<h2>Forma 1: addslashes() no PHP</h2>
<p>É a forma mais simples (e ingênua) de se tratar o problema. Por exemplo, se queremos nos proteger das aspas simples, poderíamos simplesmente escapá-las no PHP da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$login</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$senha</span> <span style="color: #339933;">=</span> <span style="color: #990000;">addslashes</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'senha'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Dessa forma, caso uma aspa simples chegasse do usuário, seria devidamente <em>escapada</em> com uma &#8220;\&#8221; antes, e o servidor SQL não iria interpretá-la como um delimitador.<br />
Para o nosso exemplo de ataque, resolveria.<br />
O grande problema com esta solução é que ela só prevê ataques que usem aspas simples. Bancos de dados diferentes podem usar caracteres de controle diferentes, como aspas duplas, quebras de linha, ou outras coisas mais estranhas. E checar por todas estas formas é longe de ser a maneira mais eficaz (e viável!) de se proceder.<br />
Temos uma outra opção, suportada por vários bancos de dados.</p>
<h2>Forma 2: deixar o próprio banco escapar</h2>
<p>A segunda opção é passar a string para o banco e deixar ele se virar. Afinal, ele sabe o que pode e o que não pode entrar em uma string. No MySQL, isso poderia ser feito da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$login</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_real_escape_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$senha</span> <span style="color: #339933;">=</span> <span style="color: #990000;">mysql_real_escape_string</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'senha'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Segundo a documentação, chamando esta função, o banco escapa automaticamente as seguintes sequencias: \x00, \n, \r, \, &#8216;, &#8221; e \x1a. Ou seja, pelo visto as aspas simples não eram nosso único problema mesmo.<br />
Existem funções semelhantes para outros bancos de dados (por exemplo, <em>pg_escape_string()</em> para o PostgreSQL).<br />
Porém, a solução que considero mais elegante é usar consultas preparadas.</p>
<h2>Forma 3: consultas preparadas</h2>
<p>A idéia de se preparar uma consulta é dizer ao banco de dados o formato da consulta (apenas os parâmetros formais), e fazer a amarração dos parâmetros reais somente na hora da execução.<br />
A maior parte dos bancos de dados suportam consultas preparadas, mas vou mostrar o exemplo usando MySQL, devido a popularidade.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$dbh</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> mysqli<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;localhost&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;ususario&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;senha&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;banco&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$dbh</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prepare</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT * FROM usuarios WHERE login = ? AND senha = ?&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;login&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'login'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind_param</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;senha&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'senha'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$c</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Ou seja, primeiro informamos ao banco qual será a consulta a ser executada. Perceba que usamos interrogações no lugar dos parâmetros reais. Com isso, o banco prepara a consulta pra ser executada.<br />
Logo em seguida, dizemos ao banco o valor que cada parâmetro irá receber. Esta etapa se chama amarração (binding). Como o banco de dados sabe o tipo de cada campo, ele também sabe como proceder pra escapar corretamente cada valor.<br />
E por último, executamos a consulta. Simples, fácil e seguro!</p>
<h2>Conclusão</h2>
<p>SQL Injection é um problema sério que afeta muitos aplicativos web por aí afora, porém é um problema que só existe por causa da ingenuidade dos programadores, que não programam pensando em segurança. A solução, como vimos, é bem simples.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached" title="Otimização de sites com memcached">Otimização de sites com memcached</a></li><li><a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo" title="Os 10 piores CAPTCHAs do mundo">Os 10 piores CAPTCHAs do mundo</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-spam-em-formularios" title="Evitando spam em formulários">Evitando spam em formulários</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Otimização: imagens inline</title>
		<link>http://www.ataraxia.com.br/posts/otimizacao-imagens-inline</link>
		<comments>http://www.ataraxia.com.br/posts/otimizacao-imagens-inline#comments</comments>
		<pubDate>Fri, 17 Apr 2009 14:48:33 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[dicas]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[otimização]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=216</guid>
		<description><![CDATA[Sempre que queremos colocar uma imagem em uma página, podemos usar a tag img: &#60;img src=&#34;imagem.png&#34; /&#62; ou então, podemos carregá-la como imagem de fundo de um elemento qualquer usando CSS: .classe &#123; background-image:url&#40;imagem.png&#41;; &#125; Um dos problemas em páginas que possuem muitas imagens é que cada imagem requer a abertura de uma nova conexão [...]]]></description>
			<content:encoded><![CDATA[<p>Sempre que queremos colocar uma imagem em uma página, podemos usar a tag <b>img</b>:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;imagem.png&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>ou então, podemos carregá-la como imagem de fundo de um elemento qualquer usando <acronym title="Cascating Style Sheet">CSS</acronym>:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.classe</span> <span style="color: #00AA00;">&#123;</span> <span style="color: #000000; font-weight: bold;">background-image</span><span style="color: #00AA00;">:</span><span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">imagem.png</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span> <span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Um dos problemas em páginas que possuem muitas imagens é que cada imagem requer a abertura de uma nova conexão HTTP, e com a limitação de 2 conexões por host (é uma restrição dos navegadores que seguem a especificação HTTP), o tempo de carga da página pode acabar crescendo bastante.</p>
<h2>A lógica</h2>
<p>Uma solução para este problema é ao invés de carregar as imagens externas, colocá-las diretamente dentro da página, seguindo a mesma lógica que já usamos com CSS. Por exemplo, podemos especificar uma folha de estilo externa:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;arquivo.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>ou então podemos colocar os estilos inline:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">style</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span>&gt;</span>
.classe1 { font-color:#f00; }
#id2 { width:200px; }
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">style</span>&gt;</span></pre></div></div>

<h2>Codificando a imagem</h2>
<p>Até aí, tudo bem, afinal CSS é texto, e texto entra bem dentro de uma página. Mas como colocar uma imagem dentro de uma página, uma vez que a imagem é binária?<br />
Simples! Primeiro, codificamos a imagem de binário para ASCII usando a codificação <b>base64</b>. Existem várias formas de se fazer isso, e boa parte das linguagens de programação disponibiliza funções para fazer esta codificação. Por exemplo, em PHP, podemos fazer:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">print</span> base64encode<span style="color: #009900;">&#40;</span><span style="color: #990000;">file_get_contents</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;arquivo.png&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>A saída disso é algo mais ou menos assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">iVBORw0KGgoAAAANSUhEUgAAAxYAAAAKCAAAAAAMKZcGAAAACXZwQWcAAAMWAAAACgALWq6
YAAAAOklEQVRYw<span style="color: #339933;">+</span>3TsQ0AIAwEMZT9F4Uh8vTUFCDZM9zV6nyt08kMXOypBnCwBdgCbAG2AF
uALcAWYAt4xQZXmxLmG7UZ3wAAAABJRU5ErkJggg<span style="color: #339933;">==</span></pre></div></div>

<p>Pronto, já temos a representação codificada da imagem.<br />
Para que a saída coubesse na tela, quebrei a saída em 3 linhas. A saída real é toda em uma só linha, mas como veremos adiante, tanto faz, pois podemos usar quebras de linha.</p>
<h2>URLs do tipo &#8220;data&#8221;</h2>
<p>Antes de colocarmos a imagem dentro da página, precisamos ver como funcionam as URLs do tipo &#8220;data&#8221;. A URL segue o seguinte formato:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;">data:[<span style="color: #009900;">&lt;tipo MIME&gt;</span>][;charset=&quot;<span style="color: #009900;">&lt;charset&gt;</span>&quot;][;base64],<span style="color: #009900;">&lt;dados&gt;</span></pre></div></div>

<p>onde:</p>
<ul>
<li><em>tipo MIME</em> é o tipo do arquivo que vamos colocar, no nosso caso, <b>image/png</b>;</li>
<li><em>charset</em> é a codificação utilizada, para o caso de arquivos texto (não usaremos no nosso exemplo).</li>
<li><em>base64</em> é a codificação utilizada. Se for omitida, o navegador entenderá que estamos usando US-ASCII, e no caso de imagens, não vai dar certo;</li>
<li>e por último, <em>dados</em> contém a string com o arquivo codificado (aquela sequencia grande de caracteres ali de cima). A string pode ser quebrada com espaços ou quebras de linha.</li>
</ul>
<p></p>
<h2>Juntando tudo</h2>
<p>Pois bem, agora que temos a representação codificada da imagem e já sabemos usar URLs do tipo &#8220;data&#8221;, podemos colocá-la diretamente na página, usando a própria tag <b>img</b>:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAxYAAAAKCAAAAAAMKZc</span>
<span style="color: #009900;">GAAAACXZwQWcAAAMWAAAACgALWq6YAAAAOklEQVRYw+3TsQ0AIAwEMZT9F4Uh8vTUFCDZM9zV6n</span>
<span style="color: #009900;">yt08kMXOypBnCwBdgCbAG2AFuALcAWYAt4xQZXmxLmG7UZ3wAAAABJRU5ErkJggg==&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>Ou então uma regra de CSS, da seguinte forma:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.classe</span> <span style="color: #00AA00;">&#123;</span> <span style="color: #000000; font-weight: bold;">background-image</span><span style="color: #00AA00;">:</span><span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span>data<span style="color: #00AA00;">:</span>image/png<span style="color: #00AA00;">;</span>base64<span style="color: #00AA00;">,</span>iVBORw0KGgoAAAANSUh
EUgAAAxYAAAAKCAAAAAAMKZcGAAAACXZwQWcAAAMWAAAACgALWq6YAAAAOklEQVRYw<span style="color: #00AA00;">+</span>3TsQ0
AIAwEMZT9F4Uh8vTUFCDZM9zV6nyt08kMXOypBnCwBdgCbAG2AFuALcAWYAt4xQZXmxLmG7U
Z3wAAAABJRU5ErkJggg<span style="color: #00AA00;">==</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span> <span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>É claro que usar esta técnica, como quase tudo na vida, tem várias vantagens e desvantagens.</p>
<h2>As vantagens</h2>
<p>Temos várias vantagens em usar um esquema deste tipo:</p>
<ul>
<li>Suporte na grande maioria dos navegadores modernos: Firefox, Opera, Safari, Konqueror e Chrome;</li>
<li>Antes de mais nada, estamos diminuindo o número de requisições HTTP, e consequentemente, evitamos o tráfego associado à requisição (cabeçalhos HTTP);</li>
<li>Como a imagem está inline, conseguimos &#8220;fugir&#8221; do limite de 2 conexões por host, já que estamos evitando a abertura de novas conexões;</li>
<li>Para imagens pequenas, temos um ganho real em bytes transferidos, pois embora a imagem codificada em base64 fique maior, estamos evitando de enviar os cabeçalhos HTTP (que somam em média 200 bytes).</li>
<li>Conexões seguras (que usam https) só mostram o &#8220;cadeado&#8221; fechado se todos os elementos externos forem carregados através de https também. E o <em>overhead</em> associado a uma conexão https é bem maior que o de uma conexão http normal. Com a imagem inline, ganhamos mais um pouco.</li>
</ul>
<p></p>
<h2>As desvantagens</h2>
<p>Temos várias desvantagens, algumas contornáveis:</p>
<ul>
<li>Internet Explorer até a versão 7 não tem suporte. Só a partir do 8. A forma de se usar para os dois navegadores é usando arquivos CSS separados para cada navegador (ou um pré-processador de CSS que detecte o navegador e dê a saída com o que for suportado);</li>
<li>Imagem inline em uma página (usando tag <b>img</b>) não são cacheadas pelo navegador. Se usada dentro do CSS, aí sim teremos o cache em ação, pois o navegador irá cachear o CSS;</li>
<li>Uma imagem codificada em base64 tem seu tamanho aumentado em 33%. Para imagens grandes, é uma perda considerável, mas para imagens pequenas (da ordem de 500 bytes), temos um ganho, pois mesmo com o aumento da imagem, estamos evitando o envio dos cabeçalhos, e podemos sair ganhando na soma;</li>
<li>Dificuldade de manutenção: se uma imagem é alterada, ela precisa ser recodificada. Existem formas de se automatizar isso.</li>
</ul>
<p></p>
<h2>Um exemplo</h2>
<p>A imagem que aparece aqui embaixo está inline, e foi colocada usando uma tag <b>img</b> (a qualidade está baixa pra não ficar muito grande):</p>
<p><img src="data:image/png;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAFA3PEY8MlBGQUZaVVBfeMiCeG5uePWvuZHI////////////////////////////////////////////////////2wBDAVVaWnhpeOuCguv/////////////////////////////////////////////////////////////////////////wAARCADwAUADASIAAhEBAxEB/8QAGAAAAwEBAAAAAAAAAAAAAAAAAAECAwT/xAAxEAACAgEDBAEEAgEEAwADAAABAgARIQMSMSJBUWETMnGBkaHwwSMzQrFS0eFigvH/xAAWAQEBAQAAAAAAAAAAAAAAAAAAAQL/xAAdEQEBAQADAQEBAQAAAAAAAAAAEQEhMUFhAlFx/9oADAMBAAIRAxEAPwDHev8A4j9RbwPUkmhxmRN7rV1puvvK27gRMZemxuozf6l/pVQoxULmxKsOpbPmAOmvIz7jcUtNcWR9sxM1Gh2lq25pmykE3x2l8Auob6uJq4sBhkV2mAGfM3J+OjeaqMMZKttXM3ZlApvx5EzGsSabj1K1VJO4cHv4hapSu0lATQ7yRquHonHePRUqpY4HuNH0y4oEHtZxBRqIzHi/xLcKQAzUarMzdnGpg1niW6bm5APgmFoYqtLRMZB3gAWv2g7KpClb7Xcqn+Uc1f4gqNg3HjAi2bh9MtQoZipsgcQvfpm6XMVagoq4Ni4DSqzUskKFwG9yttapN2a4ilZBQynFVGy0AR+5QO4MCAoHcQGNOtMkxSpcBKJGfEGQMQwIA94jP+2DqDP8xH/VQbceoSlqi1AGRXPmNCfjtsgeYC9PT93JR2clWG4QUhq9VbQB6jbSB7gAeYbFDWWH+Yteya7VcChQUgG+9zmYcY5mmjYbFynCEWSVvmO0tTpDJ7YlM4X6gD9xGpWqX9+Zi2STHh4v5QccfiGopK2JiJshG3qyCIzambe2TA1EBNW0zZK5BkBGPMm4bgUG5Q5wazKVdq1+8SHNfcTXWL0l+ZPaWQSPckYGZjcZKUv1DzF9poiUNx/EZgDjMzM1PUD/ABM6oUZf0aSmjjmb3jIBHOZiqljQE2f6SBmME/Iq4VR95RHyICpsjNeZhU20VtT9xmMpUrpOW+kj7zR3OnQQ58zJtRiecTVafT6sEdxFKWm/yWrm7HMp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" /></p>
<p>Clicando o botão direito na imagem e escolhendo &#8220;Exibir imagem&#8221; (no Firefox ou em outro navegador que dê suporte), dá pra se ver na barra de endereços a URL usada pra criar a imagem.<br />
E claro, se você não está vendo imagem nenhuma, provavelmente está usando o Internet Explorer. E já passou da hora de passar a usar um <a href="http://www.getfirefox.com/">navegador decente, que suporta os padrões web</a>, não é?</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/evitando-conteudo-duplicado" title="Evitando conteúdo duplicado">Evitando conteúdo duplicado</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached" title="Otimização de sites com memcached">Otimização de sites com memcached</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-parte-3-cache" title="Otimização de sites, parte 3 &#8211; Cache">Otimização de sites, parte 3 &#8211; Cache</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-parte-2-compressao" title="Otimização de sites, parte 2 &#8211; Compressão">Otimização de sites, parte 2 &#8211; Compressão</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/otimizacao-imagens-inline/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Criando CAPTCHAs em PHP</title>
		<link>http://www.ataraxia.com.br/posts/criando-captchas-em-php</link>
		<comments>http://www.ataraxia.com.br/posts/criando-captchas-em-php#comments</comments>
		<pubDate>Sun, 12 Apr 2009 03:06:23 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[captcha]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[segurança]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=236</guid>
		<description><![CDATA[Após postar a galeria dos 10 piores CAPTCHAs do mundo, estou postando o artigo prometido sobre como criar um CAPTCHA em PHP. Como já dito antes, a função de um CAPTCHA é apresentar um problema de fácil solução para um ser humano, mas de difícil resolução por um computador. Normalmente, os CAPTCHAs tomam a forma [...]]]></description>
			<content:encoded><![CDATA[<p>Após postar a <a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo">galeria dos 10 piores CAPTCHAs do mundo</a>, estou postando o artigo prometido sobre como criar um CAPTCHA em PHP.<br />
Como já dito antes, a função de um <acronym title="Completely Automated Public Turing test to tell Computers and Humans Apart">CAPTCHA</acronym> é apresentar um problema de fácil solução para um ser humano, mas de difícil resolução por um computador. Normalmente, os CAPTCHAs tomam a forma de imagens com letras distorcidas, e é exatamente este o tipo que iremos criar neste artigo.</p>
<h2>Como funciona na teoria?</h2>
<p>O funcionamento de um CAPTCHA de letras tortas é bem simples. O servidor gera uma string que será transformada em uma imagem. A string é salva em algum lugar (normalmente em uma variável de sessão). A imagem é apresentada dentro de um formulário. Ao submeter o formulário, o script checa se o que o usuário digitou bate com o conteúdo da variável de sessão. Se bater, o usuário passou no teste.<br />
Na teoria, tudo muito simples.</p>
<h2>Mas e na prática?</h2>
<p>Na prática, tudo também pode ser igualmente simples. Ao invés de reinventar a roda, podemos utilizar uma classe chamada <a href="http://www.phpcaptcha.org/">Securimage</a>, que serve justamente para gerar CAPTCHAs.</p>
<h2>Securimage</h2>
<p>Securimage é uma classe em PHP que utiliza a biblioteca gráfica GD para gerar imagens com CAPTCHAs. A classe é bastante versátil, e suporta várias opções, como fontes <acronym title="TrueType Font">TTF</acronym>, imagens de fundo, linhas, arcos e bem mais.<br />
O primeiro passo é baixar o pacote com a <a href="http://www.phpcaptcha.org/download/">versão mais recente</a> e descompactá-lo em algum lugar. A partir deste ponto, vou assumir que o pacote foi descompactado em uma pasta chamada &#8220;securimage&#8221; no diretório raiz do site.</p>
<h2>Criando o form com a imagem</h2>
<p>Dentro do formulário que se deseja proteger, colocamos uma tag <b>img</b>, que irá conter a imagem gerada pelo Securimage:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;captcha&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/securimage/securimage_show.php&quot;</span> <span style="color: #000066;">alt</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;CAPTCHA&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>Este script <b>securimage_show.php</b> é bem pequeno (3 linhas), e irá criar um CAPTCHA com as opções padrões da classe. Veremos mais adiante algumas formas de se customizar a imagem.<br />
Além da imagem, também precisamos de um campo para o usuário digitar as letras contidas na imagem:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">input</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;captcha_txt&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>E com isso o formulário está pronto.</p>
<h2>A checagem no backend</h2>
<p>O usuário viu a imagem, digitou os dados e submeteu o formulário. Agora é hora de checar se o código digitado bate com o texto contido na imagem.<br />
Logo no início do script que recebe os dados do formulário (em caso de dúvida, veja o atributo <b>action</b> da tag <b>form</b>), é preciso inicializar as variáveis de sessão:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">session_start</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>É importante que este código venha antes de qualquer saída, ou teremos um erro do tipo &#8220;Cannot modify header information &#8211; headers already sent&#8230;.&#8221;. Na dúvida, coloque logo no início.<br />
O restante da checagem é bastante simples. Basta instanciarmos um objeto da classe Securimage e chamar um método que faz a checagem:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'DOCUMENT_ROOT'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/securimage/securimage.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$securimage</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Securimage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$securimage</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">check</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_POST</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'captcha_txt'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Código digitado corretamente</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Ok, o código foi digitado corretamente.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// Código digitado não bate com a imagem</span>
    <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Erro: código incorreto.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>O exemplo acima apenas ilustra como é feita a checagem. As chamadas a <b>die()</b> devem ser substituídas de acordo com a lógica da página onde o CAPTCHA está sendo inserido. No caso do código estar correto, deve-se prosseguir com o processamento do formulário, e caso não esteja, possivelmente exibir novamente o formulário com uma mensagem de erro. Será gerado um novo CAPTCHA automaticamente.</p>
<h2>Outras opções</h2>
<p>Como dito anteriormente, a classe é bastante versátil, e suporta diversas opções para a geração das imagens. Todas as opções estão descritas na <a href="http://www.phpcaptcha.org/Securimage_Docs/Securimage/classes/Securimage.html">documentação da classe</a>, mas vou transcrever várias das opções aqui.<br />
Para se customizar a imagem, basta editar diretamente o script <b>securimage_show.php</b>, que é o script usado na tag <b>img</b>. Originalmente, ele é apenas o seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'securimage.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$img</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> securimage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Podemos passar opções para a classe antes de chamar o método <b>show()</b>. Apenas para ilustrar, aqui vai um exemplo bem customizado:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">include</span> <span style="color: #0000ff;">'securimage.php'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$img</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> securimage<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">code_length</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">8</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// 8 ao invés de apenas 4 caracteres</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">charset</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;AEIOU&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Apenas vogais</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">image_width</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">280</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Padrão é 175px para 4 caracteres</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">multi_text_color</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;#ff0000,#0000ff&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Letras azuis e vermelhas</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">image_bg_color</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;#ffff00&quot;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// Fundo amarelo</span>
<span style="color: #000088;">$img</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">show</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>E abaixo, 3 exemplos de CAPTCHAs gerados por este script:</p>
<p><img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/11.png" alt="CAPTCHA - Exemplo 1" title="CAPTCHA - Exemplo 1" width="280" height="45" class="alignnone size-full wp-image-251" /><br />
<img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/21.png" alt="CAPTCHA - Exemplo 2" title="CAPTCHA - Exemplo 2" width="280" height="45" class="alignnone size-full wp-image-252" /><br />
<img src="http://www.ataraxia.com.br/wp-content/uploads/2009/04/31.png" alt="CAPTCHA - Exemplo 3" title="CAPTCHA - Exemplo 3" width="280" height="45" class="alignnone size-full wp-image-253" /></p>
<p>Como já dito, a classe suporta muitas outras opções, o melhor mesmo é ler a documentação caso se deseje customizar mais.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/os-10-piores-captchas-do-mundo" title="Os 10 piores CAPTCHAs do mundo">Os 10 piores CAPTCHAs do mundo</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-spam-em-formularios" title="Evitando spam em formulários">Evitando spam em formulários</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/criando-captchas-em-php/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Pegadinhas no PHP</title>
		<link>http://www.ataraxia.com.br/posts/pegadinhas-no-php</link>
		<comments>http://www.ataraxia.com.br/posts/pegadinhas-no-php#comments</comments>
		<pubDate>Sun, 05 Apr 2009 18:11:02 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[dicas]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=205</guid>
		<description><![CDATA[Depois de quase ficar maluco por causa de problemas com arredondamento de números com ponto flutuante, decidi escrever sobre alguns problemas que provavelmente muita gente já passou, e que continuam pegando muita gente. Comparação em ponto flutuante As variáveis do tipo float sofrem de um problema de precisão, pois dependendo do número, ele pode não [...]]]></description>
			<content:encoded><![CDATA[<p>Depois de quase ficar maluco por causa de problemas com arredondamento de números com ponto flutuante, decidi escrever sobre alguns problemas que provavelmente muita gente já passou, e que continuam pegando muita gente.</p>
<h2>Comparação em ponto flutuante</h2>
<p>As variáveis do tipo <em>float</em> sofrem de um problema de precisão, pois dependendo do número, ele pode não ter uma representação binária (em potências de 2) exata. Para nos resolver, o PHP (e a grande maioria das linguagens) faz o arredondamento do número. Por exemplo, se fizermos o seguinte teste:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color:#800080;">0.1</span> <span style="color: #339933;">+</span> <span style="color:#800080;">0.2</span> <span style="color: #339933;">==</span> <span style="color:#800080;">0.3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// saída:  bool(false)</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Claro que, matematicamente falando, 0.1 + 0.2 é igual a 0.3. Porém, a forma como o PHP guarda esses números internamente não é exata. Para vermos como o PHP guarda cada um desses números, podemos chamar a função <a href="http://br.php.net/serialize">serialize()</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">print</span> <span style="color: #990000;">serialize</span><span style="color: #009900;">&#40;</span><span style="color:#800080;">0.1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// d:0.1000000000000000055511151231257827021181583404541015625;</span>
<span style="color: #b1b100;">print</span> <span style="color: #990000;">serialize</span><span style="color: #009900;">&#40;</span><span style="color:#800080;">0.2</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// d:0.200000000000000011102230246251565404236316680908203125;</span>
<span style="color: #b1b100;">print</span> <span style="color: #990000;">serialize</span><span style="color: #009900;">&#40;</span><span style="color:#800080;">0.3</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// d:0.299999999999999988897769753748434595763683319091796875;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>E fazendo a conta, fica evidente que 0.1 + 0.2 não dá 0.3. E então, como fazer para comparar variáveis do tipo float sem chance de errarmos?<br />
Uma forma é definir uma constante, que por convenção chamarei de EPSILON, que terá o valor do menor número fracionário possível. Qual valor colocar? Depende da aplicação! Se sua aplicação mexe com valores financeiros, normalmente você precisa se preocupar com frações de 2 ou 3 casas decimais no máximo. Podemos então definir o EPSILON, com uma boa margem de segurança, para 1e-5, ou seja, 0.00001.<br />
Tendo esta constante, se queremos checar se dois números são iguais, podemos simplesmente checar se a diferença entre eles é menor que EPSILON. Caso seja menor, podemos considerar os números iguais. Da mesma forma, podemos fazer a comparação entre floats da mesma forma.<br />
Uma função simples, que tem o retorno semelhante à função de comparação de strings <a href="http://br.php.net/strcmp">strcmp()</a>, mas que serve para comparar floats poderia ser definida assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">define</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;EPSILON&quot;</span><span style="color: #339933;">,</span> <span style="color:#800080;">1e-5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> floatcmp<span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #339933;">,</span> <span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$diff</span> <span style="color: #339933;">=</span> <span style="color: #990000;">abs</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #339933;">-</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$diff</span> <span style="color: #339933;">&lt;</span> EPSILON<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #339933;">&lt;</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span> ? <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span> <span style="color: #339933;">:</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Esta função recebe dois números como parâmetro. Se os números forem iguais, ou seja, se a diferença entre eles for menor que a nossa margem de erro aceitável EPSILON, a função retorna 0, caso contrário retorna -1 se o primeiro número for menor, ou então 1 caso o segundo seja o menor. Bastante simples e eficaz.<br />
Para fazermos o teste acima, podemos agora proceder assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>floatcmp<span style="color: #009900;">&#40;</span><span style="color:#800080;">0.1</span><span style="color: #339933;">+</span><span style="color:#800080;">0.2</span><span style="color: #339933;">,</span> <span style="color:#800080;">0.3</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;são iguais&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;são diferentes&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>O resultado, como esperado, será &#8220;são iguais&#8221;.</p>
<h2>Números começados com zero</h2>
<p>Outro problema muito comum, principalmente quando estamos lidando com datas, é o da comparação de números iniciados com 0. Por exemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color:#800080;">09</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">9</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// saída:  bool(false)</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Isto ocorre porque o PHP trata qualquer número iniciado com 0 como um número octal, ou seja, na base 8. Caso o número não seja um octal válido, a conversão para no primeiro dígito inválido. No caso acima, 09 vira 0 (pois não existe 9 na base octal).<br />
Para fazer esta comparação, uma das formas seria a seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;09&quot;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">9</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// saída:  bool(true)</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Agora, temos a string &#8220;09&#8243;, que será convertida no inteiro 9 (base 10 mesmo) antes da comparação, e aí sim, o resultado será o esperado.</p>
<h2>Busca de strings com strpos()</h2>
<p>É muito comum usarmos a função <a href="http://br.php.net/strpos">strpos()</a> para buscarmos strings. O formato da função é:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">int <span style="color: #990000;">strpos</span> <span style="color: #009900;">&#40;</span>string <span style="color: #000088;">$haystack</span><span style="color: #339933;">,</span> mixed <span style="color: #000088;">$needle</span>  <span style="color: #009900;">&#91;</span><span style="color: #339933;">,</span> int <span style="color: #000088;">$offset</span><span style="color: #339933;">=</span><span style="color: #cc66cc;">0</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span></pre></div></div>

<p>onde <em>haystack</em> é onde estamos fazendo a busca, e <em>needle</em> é o que queremos encontrar. O retorno desta função é a posição onde a string foi encontrada, ou false caso ela não seja encontrada. O terceiro parâmetro, opcional, serve para informar a partir de que posição queremos fazer a busca.<br />
Façamos o seguinte teste:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'abcdefg'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'abc'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;encontrei&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;não encontrei&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>A saída deste exemplo é &#8220;não encontrei&#8221;, mesmo com a string &#8220;abc&#8221; tendo sido encontrada na string &#8220;abcdefg&#8221;. O grande problema, neste exemplo, é que a string foi encontrada na posição 0. Logo, a função strpos() retorna 0. E o valor 0, em uma comparação booleana, é equivalente a false, e por isto o resultado acaba não sendo o esperado.<br />
A forma correta de se fazer este teste é utilizando o operador ===, que além de checar o valor, também checa o tipo do retorno. Podemos fazer assim:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'abcdefg'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'abc'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;encontrei&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">print</span> <span style="color: #0000ff;">&quot;não encontrei&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>E agora, teremos o resultado esperado &#8220;encontrei&#8221;.</p>
<p>Existem várias outras &#8220;pegadinhas&#8221; no PHP (já escrevi por exemplo, sobre os operadores <b>and</b> e <b>or</b>, no <a href="http://www.ataraxia.com.br/posts/precedencia-no-php">artigo sobre precedência</a>), que muitos podem considerar como bug ou algum problema sério da linguagem, mas a maior parte dos problemas tem uma explicação lógica.<br />
Retirei parte dos exemplos de um post na <a href="http://devzone.zend.com/node/view/id/168">Zend Developer Network</a>, e como passei por problemas com floats recentemente, achei que seria interessante compartilhar.<br />
Caso alguem tenha mais algumas &#8220;pegadinhas&#8221; para compartilhar, fique a vontade para fazer um comentário.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/pegadinhas-no-php/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Otimização em PHP, parte 1: Minify</title>
		<link>http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify</link>
		<comments>http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify#comments</comments>
		<pubDate>Thu, 26 Feb 2009 04:13:37 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[dicas]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[otimização]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/?p=196</guid>
		<description><![CDATA[Este é o primeiro artigo de uma série sobre otimização de páginas. Existem muitas técnicas que podemos utilizar pra melhorar o desempenho e o tempo de carregamento de uma página. Existem alguns fatores que influenciam no tempo de carregamento de uma página: Tamanho total dos dados Tempo de geração da página Número de conexões HTTP [...]]]></description>
			<content:encoded><![CDATA[<p>Este é o primeiro artigo de uma série sobre otimização de páginas. Existem muitas técnicas que podemos utilizar pra melhorar o desempenho e o tempo de carregamento de uma página.</p>
<p>Existem alguns fatores que influenciam no tempo de carregamento de uma página:</p>
<ul>
<li>Tamanho total dos dados</li>
<li>Tempo de geração da página</li>
<li>Número de conexões <acronym title="HyperText Transfer Protocol">HTTP</acronym> necessárias</li>
</ul>
<p>O tamanho total dos dados é de extrema importância, pois quanto mais dados pra se transferir (páginas, imagens, folhas de estilo, scripts externos, etc), maior o tempo de carregamento de uma página. O tempo de geração também é importante, e este tempo depende de uma programação eficiente e de um banco de dados rápido.</p>
<p>Porém, o número de conexões necessárias é frequentemente esquecido, e é um fator de extrema importância para que uma página seja carregada rapidamente.</p>
<p>Para entendermos o porque, precisamos saber o que o navegador faz quando pedimos para ele abrir uma página.</p>
<p>Primeiramente, é realizada uma consulta ao servidor <acronym title="Domain Name System">DNS</acronym> para se determinar o endereço do servidor que estamos tentando acessar. Esta consulta leva algum tempo, mas normalmente é cacheada pelo navegador uma vez feita. Num segundo passo, temos a primeira conexão, que baixa a página que foi pedida.</p>
<p>Após a busca da página, o navegador analisa sua estrutura, e busca elementos externos necessários, como imagens, folhas de estilo (<acronym title="Cascading Style Sheet">CSS</acronym>), scripts, arquivos de Flash, etc etc.</p>
<p>Cada elemento externo a ser baixado exige a abertura de mais uma conexão HTTP (nem sempre&#8230; existe pipelining e outras coisas que melhoram isso, mas pra simplificar, vou ignorar por enquanto). Cada conexão, para ser estabelecida, leva um tempo antes da transferência de dados ser iniciada. Este overhead gera um atraso, visto que muitas vezes, dependendo do tamanho do arquivo, o tempo para se estabelecer a conexão chega a ser maior que o tempo para se baixar o arquivo.</p>
<p>Some-se a isso uma regra que diz que navegadores devem abrir no máximo 2 conexões simultâneas por host. Ou seja, se a página possui 30 elementos externos a serem baixados, as conexões serão estabelecidas duas a duas até que os 30 sejam completados. Algo que se pode fazer para melhorar isto é dividir os elementos externos em alguns hosts diferentes, já que a regra manda 2 conexões <strong>por host</strong>, mas isto fica para mais adiante.</p>
<p>Muitas vezes, uma página possui vários arquivos CSS e vários scripts em JavaScript. Ao invés de utilizar, digamos, 5 tags para se carregar 5 arquivos CSS diferentes, e mais 10 tags para carregarmos 10 scripts externos, não seria muito melhor se pudéssemos abrir apenas duas conexões, e baixar todo o CSS em uma, e todo o JavaScript em outra? E melhor, que ao fazer isto eles já viessem &#8220;condensados&#8221;, de forma a diminuir seu tamanho?</p>
<p>Pois bem, a idéia do <a href="http://code.google.com/p/minify/">Minify</a> é justamente fazer isto. O Minify é um script em PHP que recebe uma lista de arquivos como parâmetro (CSS ou JavaScript) e &#8220;junta&#8221; todos eles em um único download (ele faz mais, mas para mais detalhes, veja direto na página do Minify).</p>
<p>Para fazer a instalação, tudo muito simples. Basta descompactar o arquivo na raiz do site, e fazer algumas modificações nas tags. Ao invés de termos:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/script1.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/script2.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/script3.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/script4.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/js/script5.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></pre></div></div>

<p>passamos a ter somente:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">script</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/min/?f=/js/script1.js,/js/script2.js,/js/script3.js,/js/script4.js,/js/script5.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">script</span>&gt;</span></pre></div></div>

<p>Ou seja, chamamos somente o &#8220;/min/&#8221;, e passamos como parâmetro (chamado <b>f</b>) uma lista com os scripts, separados por vírgulas, e o Minify se encarrega do resto. Com o CSS, a mesma coisa. Ao invés de termos:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/css/style1.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/css/style2.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/css/style3.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/css/style4.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/css/style5.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>teremos somente:</p>

<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/min/?f=/css/style1.css,/css/style2.css,/css/style3.css,/css/style4.css,/css/style5.css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>

<p>Apenas usando o Minify, já podemos conseguir baixar o número de conexões HTTP necessárias para se carregar a página inteira, e com isso, diminuir o tempo total.</p>
<p>Um site interessante, que fornece um mapa com todos os elementos do site, assim como o tempo de carregamento de cada um é o <a href="http://tools.pingdom.com/">Full Page Test do Pingdom</a>. O tempo de cada elemento é dividido em 3: tempo para se começar, tempo para se estabelecer a conexão e a transferência em si. Olhando bem, dá pra perceber que o tamanho das páginas (parte azul da barra) tem uma influência menor do que o número de conexões.</p>
<p>Existem outras técnicas, que podem ser usadas em conjunto com o Minify para melhorar ainda mais, mas ficarão para os próximos artigos da série.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-parte-2-compressao" title="Otimização de sites, parte 2 &#8211; Compressão">Otimização de sites, parte 2 &#8211; Compressão</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-parte-3-cache" title="Otimização de sites, parte 3 &#8211; Cache">Otimização de sites, parte 3 &#8211; Cache</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-massa" title="Envio de emails em massa">Envio de emails em massa</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-de-sites-com-memcached" title="Otimização de sites com memcached">Otimização de sites com memcached</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-imagens-inline" title="Otimização: imagens inline">Otimização: imagens inline</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/acessando-sites-fora-do-ar" title="Acessando sites fora do ar">Acessando sites fora do ar</a></li><li><a href="http://www.ataraxia.com.br/posts/paginas-de-manutencao" title="Páginas de manutenção">Páginas de manutenção</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Precedência no PHP</title>
		<link>http://www.ataraxia.com.br/posts/precedencia-no-php</link>
		<comments>http://www.ataraxia.com.br/posts/precedencia-no-php#comments</comments>
		<pubDate>Sun, 15 Feb 2009 19:50:28 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[dicas]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.ataraxia.com.br/blog/?p=191</guid>
		<description><![CDATA[Todo mundo que programa em PHP, em algum ponto já deve ter usado os operadores lógicos &#124;&#124; (ou) e &#38;&#38; (e). Quando temos uma estrutura de código do tipo: &#60;?php $a = $expressao1 &#38;&#38; $expressao2; ?&#62; O valor da variável $a será verdadeiro, se tanto $expressao1 e $expressao2 forem simultaneamente verdadeiras, e será falso caso [...]]]></description>
			<content:encoded><![CDATA[<p>Todo mundo que programa em PHP, em algum ponto já deve ter usado os operadores lógicos <b>||</b> (ou) e <b>&amp;&amp;</b> (e). Quando temos uma estrutura de código do tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$a</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$expressao1</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #000088;">$expressao2</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>O valor da variável $a será verdadeiro, se tanto $expressao1 e $expressao2 forem simultaneamente verdadeiras, e será falso caso uma das duas seja falsa.</p>
<p>Da mesma forma, temos o operador <b>and</b>, que da mesma forma que o <b>&#038;&#038;</b>, também funciona como um &#8220;e&#8221; lógico. A diferença está na precedência. O operador <b>&#038;&#038;</b> é processado antes de uma atribuição, enquanto que o operador <b>and</b> é processado depois.</p>
<p>Para ilustrar, podemos fazer o seguinte teste:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$a</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$b</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span> and <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Se alguem achar que ao executar este código, tanto $a quanto $b valerão false, abra o PHP e execute para tirar a prova. Teremos $a valendo false, e $b valendo true, o que na verdade era de se esperar.</p>
<p>Para $a, o PHP processa a expressão (true &#038;&#038; false), e atribui seu resultado (false) a $a. No caso de $b, a atribuição tem precedência, então o PHP processa primeiro a expressão &#8220;$b = true&#8221;, e depois disso faz o &#8220;e lógico&#8221; com o false (que dá false, mas não é guardado em lugar algum). Ou seja, a precedência fez a diferença neste caso. Poderíamos escrever o código da seguinte forma, para facilitar o entendimento:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$a</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#40;</span><span style="color: #000088;">$b</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>E da mesma forma que temos os dois operadores (<b>&#038;&#038;</b> e <b>and</b>), também temos os operadores <b>||</b> e <b>or</b>. A diferença entre os dois é a mesma que no caso do &#8220;and&#8221;, ou seja, apenas a precedência em relação ao operador de atribuição.</p>
<p>Ilustrando:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000088;">$a</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">||</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$b</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span> or <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$a</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$b</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Ou seja, da mesma forma que o exemplo anterior, teremos $a valendo true (pois um dos dois valores é verdadeiro), e $b valendo false, pois primeiro é feita a atribuição, e depois processado o &#8220;ou&#8221;.</p>
<p>Em caso de maiores dúvidas, a seção de <a href="http://www.php.net/manual/pt_BR/language.operators.logical.php">operadores lógicos</a> do manual do PHP certamente irá tirar qualquer dúvida.</p>
<p>Para quem pretende estudar para fazer a prova de certificação da Zend, é uma boa saber desses pequenos detalhes, pois a prova tem várias pegadinhas que podem pegar os desavisados.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php" title="Imprimindo em formulários contínuos em PHP">Imprimindo em formulários contínuos em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/precedencia-no-php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Imprimindo em formulários contínuos em PHP</title>
		<link>http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php</link>
		<comments>http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php#comments</comments>
		<pubDate>Thu, 08 Jan 2009 02:29:21 +0000</pubDate>
		<dc:creator>Bruno Lustosa</dc:creator>
				<category><![CDATA[programação]]></category>
		<category><![CDATA[impressão]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[pear]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.ataraxia.com.br/?p=161</guid>
		<description><![CDATA[Um problema que as vezes surge é a impressão em formulário contínuo. Seja nota fiscal, etiqueta, ou qualquer outra coisa, muitas vezes precisamos desenvolver uma aplicação que faça isso. O grande problema de imprimir nesse tipo de papel é saber onde a &#8220;folha&#8221; termina e começa a próxima. A solução que eu usei pra resolver [...]]]></description>
			<content:encoded><![CDATA[<p>Um problema que as vezes surge é a impressão em formulário contínuo. Seja nota fiscal, etiqueta, ou qualquer outra coisa, muitas vezes precisamos desenvolver uma aplicação que faça isso. O grande problema de imprimir nesse tipo de papel é saber onde a &#8220;folha&#8221; termina e começa a próxima.</p>
<p>A solução que eu usei pra resolver um problema de impressão de notas fiscais foi usar uma classe do PEAR chamada File_PDF, que como o próprio nome já deixa claro, serve para gerar arquivos PDF.</p>
<p>Como todos sabemos, o formato <acronym title="Portable Document Format">PDF</acronym> é ideal para situações em que precisamos ter certeza de que ele sempre será impresso da mesma forma, independente da máquina onde é aberto. O problema em usar outros formatos (DOC do Word, por exemplo), é que as informações necessárias para a impressão não ficam no arquivo. Detalhes como as fontes usadas, os tamanhos, acabam dependendo de configurações de cada máquina.</p>
<p>Voltando ao problema, eu tinha um formulário de 10 páginas para testes, com um tamanho não muito usual, e os campos da nota fiscal que eu precisaria preencher.</p>
<p>Pra resolver o problema do posicionamento, não tem outro jeito, tem que medir com régua mesmo. A idéia é anotar as posições X e Y de cada campo, usando milímetros pra evitar números fracionários. O tamanho do papel também se mede com régua, não tem muito mistério.</p>
<p>Tendo o tamanho do papel e o posicionamento de cada campo, o grande truque é gerar um PDF dinamicamente, com &#8220;páginas&#8221; do tamanho da nossa nota fiscal, e depois posicionar os textos dentro dessa página.</p>
<p>No fim do script, teremos um PDF já todo pronto pra ser mandado para a impressora, tudo já formatado com o tamanho e posição corretas.</p>
<p>Segue o código, por partes.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'File/PDF.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$pdf</span> <span style="color: #339933;">=</span> File_PDF<span style="color: #339933;">::</span><span style="color: #004000;">factory</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">Array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'orientation'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'P'</span><span style="color: #339933;">,</span>
                               <span style="color: #0000ff;">'unit'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'mm'</span><span style="color: #339933;">,</span>
                               <span style="color: #0000ff;">'format'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">Array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">206</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">165</span><span style="color: #009900;">&#41;</span>
                        <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pdf</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFont</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Courier'</span><span style="color: #339933;">,</span><span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">10</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Até aqui, sem muitos mistérios. Incluí o arquivo da classe File_PDF, e instanciei um objeto em $pdf. A orientação do documento é P (de Portrait, ou &#8220;em pé&#8221;), a unidade que eu vou usar será milímetros, e o formato da minha folha é de 206 mm de altura por 165 mm de largura. Depois disso, eu escolho a fonte Courier 10 para o documento inteiro.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$venda</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$item</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000088;">$pdf</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addPage</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'P'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pdf</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">text</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">171</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">44</span><span style="color: #339933;">,</span><span style="color: #000088;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'nome_cliente'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pdf</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">text</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">171</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">49</span><span style="color: #339933;">,</span><span style="color: #0000ff;">'Prest. Serv.'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pdf</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">text</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">171</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">57</span><span style="color: #339933;">,</span><span style="color: #000088;">$item</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'data'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #339933;">...</span>
&nbsp;
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Agora, eu percorro um vetor ($venda) já criado com as informações que eu precisarei colocar na nota fiscal. Para cada entrada desse vetor, eu crio uma nova página com a mesma orientação (em pé). A partir daí, é só posicionar cada texto. Em 171 x 44, coloco o nome do cliente, em 171 x 49, a natureza da operação, em 171 x 57, a data da venda, e por aí vai.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #990000;">header</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Content-type: application/pdf&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$pdf</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">output</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notas.pdf'</span><span style="color: #339933;">,</span><span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Para terminar, dou a saída do documento. Marco o tipo da saída para &#8220;application/pdf&#8221;, e mando o objeto soltar o documento para o navegador com o nome de &#8220;notas.pdf&#8221;. O segundo parâmetro é se a saída é inline ou como um arquivo para download. Passamos false para que o navegador entenda que o PDF é para ser baixado.</p>
<p>Se tudo deu certo, o navegador vai perguntar se você quer abrir ou salvar o PDF. Se abrir em algum programa como o Adobe Reader, basta imprimir diretamente do programa, e bingo. Resolvida a questão.</p>
<h3  class="related_post_title">Artigos relacionados</h3><ul class="related_post"><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-2-de-2" title="XML no PHP com XML_Serializer, parte 2 de 2">XML no PHP com XML_Serializer, parte 2 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/xml-no-php-com-xml_serializer-parte-1-de-2" title="XML no PHP com XML_Serializer, parte 1 de 2">XML no PHP com XML_Serializer, parte 1 de 2</a></li><li><a href="http://www.ataraxia.com.br/posts/validacao-de-dados-em-php" title="Validação de dados em PHP">Validação de dados em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/removendo-o-generator-do-wordpress" title="Removendo o &#8220;generator&#8221; do Wordpress">Removendo o &#8220;generator&#8221; do Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/escrevendo-plugins-para-o-wordpress" title="Escrevendo plugins para o Wordpress">Escrevendo plugins para o Wordpress</a></li><li><a href="http://www.ataraxia.com.br/posts/evitando-sql-injection-em-php" title="Evitando SQL injection em PHP">Evitando SQL injection em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/criando-captchas-em-php" title="Criando CAPTCHAs em PHP">Criando CAPTCHAs em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/pegadinhas-no-php" title="Pegadinhas no PHP">Pegadinhas no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/otimizacao-em-php-parte-1-minify" title="Otimização em PHP, parte 1: Minify">Otimização em PHP, parte 1: Minify</a></li><li><a href="http://www.ataraxia.com.br/posts/precedencia-no-php" title="Precedência no PHP">Precedência no PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/envio-de-emails-em-php" title="Envio de emails em PHP">Envio de emails em PHP</a></li><li><a href="http://www.ataraxia.com.br/posts/seguranca-no-envio-de-emails" title="Segurança no envio de emails em PHP">Segurança no envio de emails em PHP</a></li></ul>]]></content:encoded>
			<wfw:commentRss>http://www.ataraxia.com.br/posts/imprimindo-em-formularios-continuos-em-php/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
