<?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/"
	
xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
>

<channel>
	<title>Blog do Beraldo</title>
	<atom:link href="http://rberaldo.com.br/feed/" rel="self" type="application/rss+xml" />
	<link>http://rberaldo.com.br</link>
	<description>Sempre Berando o Conhecimento</description>
	<lastBuildDate>Sun, 11 Nov 2018 15:56:29 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=5.5.1</generator>
<site xmlns="com-wordpress:feed-additions:1">9780489</site>	<item>
		<title>PHPMailer 6: Novidades e guia de migração passo-a-passo</title>
		<link>http://rberaldo.com.br/phpmailer-6-novidades-guia-migracao/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=phpmailer-6-novidades-guia-migracao</link>
					<comments>http://rberaldo.com.br/phpmailer-6-novidades-guia-migracao/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Sat, 14 Oct 2017 12:54:08 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[phpmailer]]></category>
		<category><![CDATA[phpmailer 6]]></category>
		<category><![CDATA[smtp]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1753</guid>

					<description><![CDATA[<p>O PHPMailer 6 foi lançado no final de agosto de 2017, trazendo inúmeras novidades e melhorias em relação à versão 5. Neste artigo eu ensinei como utilizar essa biblioteca. Mas, com a nova versão 6, algumas coisas mudaram. Vamos falar sobre elas neste artigo. Também vou apresentar um guia passo-a-passo sobre como migrar do PHPMailer 5 [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/phpmailer-6-novidades-guia-migracao/">PHPMailer 6: Novidades e guia de migração passo-a-passo</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1765 size-full" src="http://rberaldo.com.br/wp-content/uploads/2017/10/phpmailer-6.jpg" alt="PHPMailer 6: Novidades e guia de migração passo-a-passo" width="560" height="292" srcset="http://rberaldo.com.br/wp-content/uploads/2017/10/phpmailer-6.jpg 560w, http://rberaldo.com.br/wp-content/uploads/2017/10/phpmailer-6-150x78.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2017/10/phpmailer-6-300x156.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2017/10/phpmailer-6-96x50.jpg 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>O PHPMailer 6 foi lançado no final de agosto de 2017, trazendo inúmeras novidades e melhorias em relação à versão 5.</p>
<p><a href="http://rberaldo.com.br/enviando-e-mails-com-a-classe-phpmailer/" target="_blank" rel="noopener">Neste artigo</a> eu ensinei como utilizar essa biblioteca. Mas, com a nova versão 6, algumas coisas mudaram.</p>
<p>Vamos falar sobre elas neste artigo. Também vou apresentar um guia passo-a-passo sobre como migrar do PHPMailer 5 para a nova versão 6.</p>
<p><span id="more-1753"></span></p>
<p>O PHPMailer 6 é uma versão que trouxe diversas melhorias e atualizações. A principal mudança está na forma de carregar a classe <code>PHPMailer</code>, que quebra a retrocompatibilidade com a versão anterior.</p>
<p>Porém, com poucas modificações, você consegue fazer a portabilidade dos seus scripts para usar o novo PHPMailer 6.</p>
<h3>Principais mudanças do PHPMailer 6</h3>
<p>Essa nova versão deixou de usar o arquivo <code>PHPMailerAutoload.php</code>. Agora a classe está em um <em>namespace</em> próprio e segue o padrão <a href="http://www.php-fig.org/psr/psr-4/" target="_blank" rel="noopener">PSR-4</a>, podendo ser carregada pelo <a href="http://rberaldo.com.br/composer-php/" target="_blank" rel="noopener">Composer</a>.</p>
<p>Além disso, não possui mais os arquivos <code>class.phpmailer.php</code>, <code>class.smtp.php</code> e <code>class.pop3.php</code>, que alguns programadores carregavam manualmente via <code>include</code>/<code>require</code>.</p>
<p>A lista completa de mudanças pode ser vista no <a href="https://github.com/PHPMailer/PHPMailer/blob/6.0/changelog.md" target="_blank" rel="noopener"><em>Changelog</em> do PHPMailer 6.0</a>.</p>
<h3>Instalando o PHPMailer 6</h3>
<p>A melhor forma de instalar dependências no PHP é usando o <a href="http://rberaldo.com.br/composer-php/" target="_blank" rel="noopener">Composer</a>. Se você ainda não conhece o Composer, sugiro que leia <a href="http://rberaldo.com.br/composer-php/" target="_blank" rel="noopener">este meu artigo</a> e comece a usá-lo! Seu trabalho ficará muito mais fácil e rápido!</p>
<p>Para instalar o PHPMailer usando o Composer, execute este comando:</p>
<pre class="brush: bash; title: ; notranslate">
composer require phpmailer/phpmailer
</pre>
<h3>Envio de Email com SMTP Autenticado usando o PHPMailer 6</h3>
<p>Feita a instalação do PHPMailer, podemos fazer nosso primeiro envio de email.</p>
<p>Vou utilizar o <a href="https://mailtrap.io" target="_blank" rel="noopener">Mailtrap</a> como SMTP. Você pode utilizar qualquer outro, inclusive o Gmail. Apenas lembre-se de que, ao usar o Gmail, você precisa <a href="https://support.google.com/a/answer/6260879?hl=pt-BR" target="_blank" rel="noopener">permitir o acesso de apps menos seguros à sua conta</a>.</p>
<p>Vamos ao script.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?php

// inclui as classes do PHPMailer
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;

// inclui o autoloader do Composer
require 'vendor/autoload.php';

// inicia a classe PHPMailer habilitando o disparo de exceções
$mail = new PHPMailer(true);
try
{
    // habilita o debug
    // 0 = em mensagens de debug
    // 1 = mensagens do cliente SMTP
    // 2 = mensagens do cliente e do servidor SMTP
    // 3 = igual o 2, incluindo detalhes da conexão
    // 4 = igual o 3, inlcuindo mensagens de debug baixo-nível
    $mail-&gt;SMTPDebug = 2;
    
    // utilizar SMTP
    $mail-&gt;isSMTP();

    // habilita autenticação SMTP
    $mail-&gt;SMTPAuth = true;

    // servidor SMTP
    $mail-&gt;Host = 'smtp.mailtrap.io'; 

    // usuário, senha e porta do SMTP
    $mail-&gt;Username = 'username';
    $mail-&gt;Password = 'senha';
    $mail-&gt;Port = 465;
    
    // tipo de criptografia: &quot;tls&quot; ou &quot;ssl&quot;
    $mail-&gt;SMTPSecure = 'tls';
    
    // email e nome do remetente
    $mail-&gt;setFrom('beraldo@ultimatephp.com.br', 'Beraldo');
    
    // Email e nome do(s) destinatário(s)
    // você pode chamar addAddress quantas vezes quiser, para
    // incluir diversos destinatários
    $mail-&gt;addAddress('destinatario1@site.com', 'Destinatário 1');
    $mail-&gt;addAddress('destinatario2@site.com', 'Destinatário 2');
    
    // endereço que receberá as respostas
    $mail-&gt;addReplyTo('contato@ultimatephp.com.br', 'ULTIMATE PHP'); 
    
    // com cópia (CC) e com cópia oculta (BCC)
    $mail-&gt;addCC('copia@site.com');
    $mail-&gt;addBCC('copia_oculta@site.com');
    
    // anexa um arquivo
    $mail-&gt;addAttachment('composer.json');

    // define o formato como HTML
    $mail-&gt;isHTML(true);
    
    // codificação UTF-8
    $mail-&gt;Charset = 'UTF-8';
    
    // assunto do email
    $mail-&gt;Subject = 'Testando o PHPMailer 6';
    
    // corpo do email em HTML
    $mail-&gt;Body    = '
&lt;h1&gt;Testando o &lt;em&gt;PHPMailer 6&lt;/em&gt;&lt;/h1&gt;

';
    
    // corpo do email em texto
    $mail-&gt;AltBody = 'Testando o PHPMailer 6';
    
    // envia o email
    $mail-&gt;send();
    
    echo 'Mensagem enviada com sucesso!' . PHP_EOL;
}
catch (Exception $e)
{
    echo 'Falha ao enviar email.' . PHP_EOL;
    echo 'Erro: ' . $mail-&gt;ErrorInfo . PHP_EOL;
}
</pre>
<p>De modo geral, o script é bem semelhante ao que apresentei no <a href="http://rberaldo.com.br/enviando-e-mails-com-a-classe-phpmailer/" target="_blank" rel="noopener">meu antigo post sobre PHPMailer (versão 5)</a>.</p>
<p>A principal diferença é a forma de carregar a classe principal, que agora segue o padrão PSR-4 e pode ser carregada pelo <em>autoloader</em> do <a href="http://rberaldo.com.br/composer-php/" target="_blank" rel="noopener">Composer</a>, o que facilita e organiza muito o nosso trabalho.</p>
<h3>Atualizando a versão do PHPMailer no Composer</h3>
<p>Caso você já utilize o PHPMailer 5, você não precisa mudar completamente seus scripts. Existe uma forma simples de atualizar para a versão 6.</p>
<p>Basta mudar a versão do pacote no <code>composer.json</code> e modificar a maneira como instanciamos a classe <code>PHPMailer</code>, seguindo o novo padrão.</p>
<p>Eu escrevi um <a href="http://www.ultimatephp.com.br/guia-phpmailer-6/" target="_blank" rel="noopener">guia gratuito passo-a-passo</a> onde mostro exatamente como fazer a migração de forma simples e rápida.</p>
<p>Também mostro mais detalhes sobre o PHPMailer 6, explicando as principais mudanças e detalhando melhor o código.</p>
<p style="text-align: center;"><a href="http://www.ultimatephp.com.br/guia-phpmailer-6/" target="_blank" rel="noopener"><strong style="font-size: 1.3em;">Clique aqui e baixe gratuitamente o meu guia sobre o novo PHPMailer 6</strong></a></p>
<p>&nbsp;</p>

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Guia Grátis de Atualização Passo-a-Passo</h2>

<div class="uphp_cta_image" style="background: #666;">
	<a href="http://www.ultimatephp.com.br/guia-phpmailer-6/" target="_blank">
        <img src="https://i1.wp.com/www.ultimatephp.com.br/wp-content/uploads/2017/09/cover-3d-308x500.png?w=185" alt="Guia Completo Sobre o PHPMailer 6" width="180">
	</a>
</div>

<div class="uphp_cta_text">
	<p>Aprenda <strong>passo-a-passo</strong> como migrar de PHPMailer 5 para o PHPMailer 6</p>
    
    <p>Novidades e mudanças da nova versão do PHPMailer</p>

	<p>Baixe <strong>gratuitamente</strong> este guia e não fique com scripts obsoletos!</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia-phpmailer-6/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/phpmailer-6-novidades-guia-migracao/">PHPMailer 6: Novidades e guia de migração passo-a-passo</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/phpmailer-6-novidades-guia-migracao/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1753</post-id>	</item>
		<item>
		<title>Não Tenha Preguiça de Ler!</title>
		<link>http://rberaldo.com.br/nao-tenha-preguica-de-ler/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=nao-tenha-preguica-de-ler</link>
					<comments>http://rberaldo.com.br/nao-tenha-preguica-de-ler/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Mon, 25 Apr 2016 18:26:09 +0000</pubDate>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[leitura]]></category>
		<category><![CDATA[preguiça]]></category>
		<category><![CDATA[Programação]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1623</guid>

					<description><![CDATA[<p>Hoje o recado é curto, mas muito importante! Até preferi gravar um vídeo rápido, pra explicar melhor. Só não liguem a má qualidade. Vídeos não são meu forte. :P A ideia é simples: se quiser trabalhar com Programação e se destacar da maioria, não tenha preguiça de ler! É importante ler documentações manuais, referências&#8230; tudo [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/nao-tenha-preguica-de-ler/">Não Tenha Preguiça de Ler!</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1625 size-full" src="http://rberaldo.com.br/wp-content/uploads/2016/04/nao-tenha-preguica-de-ler.jpg" alt="Não Tenha Preguiça de Ler!" width="560" height="292" srcset="http://rberaldo.com.br/wp-content/uploads/2016/04/nao-tenha-preguica-de-ler.jpg 560w, http://rberaldo.com.br/wp-content/uploads/2016/04/nao-tenha-preguica-de-ler-150x78.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2016/04/nao-tenha-preguica-de-ler-300x156.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2016/04/nao-tenha-preguica-de-ler-96x50.jpg 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>Hoje o recado é curto, mas muito importante!</p>
<p>Até preferi gravar um vídeo rápido, pra explicar melhor. Só não liguem a má qualidade. Vídeos não são meu forte. :P</p>
<p><span id="more-1623"></span></p>
<p><iframe src="https://www.youtube-nocookie.com/embed/VwElsGPw3LI?rel=0" width="853" height="480" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>
<p>A ideia é simples: se quiser trabalhar com Programação e se destacar da maioria, não tenha preguiça de ler!</p>
<p>É importante ler documentações manuais, referências&#8230; tudo isso ajuda a absorver conhecimentos, fazer as devidas ligações entre temas aparentemente distintos&#8230;</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/nao-tenha-preguica-de-ler/">Não Tenha Preguiça de Ler!</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/nao-tenha-preguica-de-ler/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1623</post-id>	</item>
		<item>
		<title>Como Atualizar Scripts PHP de MySQL Para MySQLi</title>
		<link>http://rberaldo.com.br/como-atualizar-php-mysql-mysqli/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-atualizar-php-mysql-mysqli</link>
					<comments>http://rberaldo.com.br/como-atualizar-php-mysql-mysqli/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Thu, 29 Oct 2015 13:43:41 +0000</pubDate>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[atualização]]></category>
		<category><![CDATA[migração]]></category>
		<category><![CDATA[mysqli]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1566</guid>

					<description><![CDATA[<p>Aprenda passo-a-passo como atualizar seus scripts PHP de MySQL para MySQLi. Apenas adicionar um "i" não é a solução!</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/como-atualizar-php-mysql-mysqli/">Como Atualizar Scripts PHP de MySQL Para MySQLi</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter size-full wp-image-1567" src="http://rberaldo.com.br/wp-content/uploads/2015/10/post-mysql-mysqli.png" alt="alt" width="560" height="292" srcset="http://rberaldo.com.br/wp-content/uploads/2015/10/post-mysql-mysqli.png 560w, http://rberaldo.com.br/wp-content/uploads/2015/10/post-mysql-mysqli-150x78.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/10/post-mysql-mysqli-300x156.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/10/post-mysql-mysqli-96x50.png 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>Atualizar para MySQLi não é apenas colocar um &#8220;i&#8221; a mais nas chamadas de funções como <code>mysql_connect</code> ou <code>mysql_query</code>, como muitos dizem.</p>
<p>Porém também não é nada muito complicado. Você apenas precisa tomar cuidado com os parâmetros de cada função.</p>
<p>Neste artigo vou mostrar como atualizar seus scripts PHP de MySQL para MySQLi.</p>
<p><span id="more-1566"></span></p>
<h2>O Motivo</h2>
<p>Como eu comentei <a href="http://rberaldo.com.br/mysql-obsoleto-php/" target="_blank" rel="noopener">neste artigo</a>, a biblioteca <code>mysql</code> está obsoleta.</p>
<p>Isso significa que você não deve usar funções como <code>mysql_connect</code>, <code>mysql_query</code> e semelhantes.</p>
<p>Em vez delas, você deve usar <code>mysqli_connect</code> e <code>mysqli_query</code></p>
<p>Porém a diferença não está apenas no &#8220;i&#8221; a mais no nome da função. A lista de parâmetros geralmente também é um pouco diferente, por isso precisamos estar atentos a isso.</p>
<h2>MySQLi ou PDO?</h2>
<p>Particularmente, recomendo e prefiro PDO. Mas há um pequeno problema&#8230;</p>
<p>PDO requer um pouco de conhecimento sobre Orientação a Objetos (OOP). E eu sei que muitos iniciantes têm bastante dificuldade com isso.</p>
<p>Por isso vou mostrar aqui como usar mysqli da forma procedural, ou seja, como usá-lo com chamadas a funções, em vez de usar a classe <code>mysqli</code> e seus métodos e propriedades.</p>
<h2>Por Que Não É Tão Simples Como Dizem</h2>
<p>Tem muita gente por aí dizendo que é só colocar o &#8220;i&#8221; nas chamadas das funções e pronto.</p>
<p>Não é bem assim.</p>
<p>Várias funções do MySQLi possuem parâmetros a mais, ordem diferente etc.</p>
<p>As funções <code>mysql_*</code> não exigiam o parâmetro de identificação da conexão (valor retornado por <code>mysql_connect</code>). Elas sempre buscavam uma conexão ativa.</p>
<p>Com mysqli a coisa é diferente&#8230;</p>
<p>É <strong>fundamental</strong> informar o identificador da conexão.</p>
<p>Dessa forma, podemos ter diversas conexões no mesmo script, sem risco de conflitos ou funcionamento inesperado.</p>
<p>Esse é só um dos exemplos.</p>
<p>Veremos isso com mais detalhes, na prática, logo logo.</p>
<h2>Banco de Dados de Exemplo</h2>
<p>Vamos criar um simples banco de dados para nossos testes.</p>
<pre lang="sql">CREATE TABLE funcionarios(
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    nome VARCHAR(50) NOT NULL,
    email VARCHAR(80) NOT NULL,
    salario DECIMAL(10,2) NOT NULL,
    nascimento DATE NOT NULL,
    PRIMARY KEY (id)
) COLLATE=utf8_unicode_ci;
</pre>
<p>Vamos inserir alguns dados:</p>
<pre lang="sql">INSERT INTO funcionarios(nome, email, salario, nascimento) VALUES
('Ana', 'ana@ana.com', 1400.00, '1993-10-16'),
('Daniela', 'dani@dani.com', 1380.50, '1996-05-15'),
('João', 'joao@joao.com', 1400.00, '1995-11-10'),
('Julia', 'julia@julia.com', 1200.95, '1997-03-22'),
('Sabrina', 'sabrina@sabrina.com', 1800.57, '1990-12-03'),
('Paulo', 'paulo@paulo.com', 1750.43, '1991-06-25');
</pre>
<h2>Exibindo os Dados Usando MySQL</h2>
<p>Vamos criar um simples script para exibir todos os dados, usando funções <code>mysql_*</code>.</p>
<pre lang="php">// dados de conexão
$host = 'localhost';
$user = 'usuario';
$pass = 'senha';
$db   = 'nome_do_banco';

// conecta com o banco de dados
$con = mysql_connect($host, $user, $pass);

// seleciona o banco de dados
mysql_select_db($db);

// efetua a consulta
$sql = "SELECT * FROM funcionarios ORDER BY nome";
$res = mysql_query($sql);

// total de resultados
$total = mysql_num_rows($res);

echo "Total de Resultados: " . $total . "<br>";

// loop pelos resultados

while ($f = mysql_fetch_array($res))
{
    echo $f['nome'] . " | " . $f['email'] . " | " . $f['salario'] . " | " . date('d/m/Y', strtotime($f['nascimento'])) . "<br>";
}

// fecha a conexão
mysql_close();
</pre>
<p>O script é super simples. Apenas um <code>SELECT</code> que lista os registros da tabela, junto ao número total de registros.</p>
<h2>Exibindo os Dados Usando MySQLi</h2>
<p>Vamos ver agora como rescrever o script anterior usando MySQLi.</p>
<p>Vou colocar o código aqui e falo sobre os principais detalhes logo em seguida.</p>
<pre lang="php">
$host = 'localhost';
$user = 'usuario';
$pass = 'senha';
$db   = 'nome_do_banco';

// conexão e seleção do banco de dados
$con = mysqlI_connect($host, $user, $pass, $db);

// executa a consulta
$sql = "SELECT * FROM funcionarios ORDER BY nome";
$res = mysqli_query($con, $sql);

// conta o número de registros
$total = mysqli_num_rows($res);

echo "Total de Resultados: " . $total . "<br>";

// loop pelos registros
while ($f = mysqli_fetch_array($res))
{
    echo $f['nome'] . " | " . $f['email'] . " | " . $f['salario'] . " | " . date('d/m/Y', strtotime($f['nascimento'])) . "<br>";
}

// fecha a conexão
mysqli_close($con);
</pre>
<p>Podemos notar três diferenças principais:</p>
<ol>
<li><code>mysqli_connect</code> permite conectar ao MySQL e já selecionar o banco de dados. Nem é necessário usar a função <code>mysqli_select_db</code>;</li>
<li>O primeiro parâmetro de <code>mysqli_query</code> <strong>não é</strong> a consulta SQL, como era com <code>mysql_query</code>. Agora é necessário passar o identificador da conexão (retornado por <code>mysqli_connect</code>) e, depois, a string com a consulta SQL;</li>
<li><code>mysqli_close</code> exige o parâmetro que identifica a conexão. Por outro lado, para <code>mysql_close</code> ele era opcional.</li>
</ol>
<p>Como você pode ver, só colocar o &#8220;i&#8221; não resolve 100%. Algumas pequenas modificações ainda são necessárias.</p>
<h2>As Listas de Parâmetros</h2>
<p>Percebeu que existem algumas diferenças nesses scripts simples?</p>
<p>Essas diferenças aumentam um pouco, caso você esteja usando outras funções, como <code>mysql_affected_rows</code>, <code>mysql_real_escape_string</code> e algumas outras.</p>
<p>Recomendo que você olhe a documentação de cada uma delas e preste atenção à lista de parâmetros de cada uma.</p>
<p>Veja qual é a ordem deles, quais são obrigatórios ou não.</p>
<p>Vou deixar aqui os links para as documentações:</p>
<ul>
<li><a href="http://php.net/manual/pt_BR/ref.mysql.php" target="_blank" rel="noopener">Lista de Funções MySQL</a></li>
<li><a href="http://php.net/manual/pt_BR/book.mysqli.php" target="_blank" rel="noopener">Lista de Funções MySQLi</a></li>
</ul>
<p>Só pra você entender melhor, parâmetros entre colchetes são opcionais. <code>resource</code> é o tipo do retorno de <code>mysql_connect</code> e <code>mysql_query</code>. <code>mysqli</code> é o identificador da conexão, retornado por <code>mysqli_connect</code> e <code>mysqli_result</code> é o retorno de <code>mysqli_query</code>.</p>
<p>Com isso você entende melhor quais são os parâmetros que cada função exige.</p>
<h2>Aprenda Com Mais Detalhes</h2>
<p>Aqui eu mostrei a ideia geral, mostrando o básico sobre a migração.</p>
<p>Escrevi um <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank" rel="noopener">guia completo sobre como atualizar de MySQL para MySQLi</a>.</p>
<p>No guia eu entro em mais detalhes, mostro uma tabela comparativa entre cada umas das funções mysql e suas correspondentes no mysqli.</p>
<p>Também mostro como usar MySQLi Orientado a Objetos, para você economizar linhas de código, facilitando o trabalho.</p>
<p>O guia é 100% Gratuito!</p>
<p><a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank" rel="noopener"><strong style="font-size: 1.1em;">CLIQUE AQUI Para Baixar o Guia Gratuitamente</strong></a></p>
<h2>Curso Completo de MySQLi</h2>
<div style="text-align: center;"><a href="https://go.hotmart.com/Y4941585Y" target="_blank" rel="noopener"><img loading="lazy" src="http://celke.com.br/img_hotmart/88665/curso-de-mysqli.jpg" width="250" height="250" border="0" /></a></div>
<p>Se você procura um curso completo sobre MySQLi, abordando os principais comandos (<code>CREATE TABLE</code>, <code>INSERT INTO</code>, <code>UPDATE</code>, <code>SELECT</code> etc), <a href="https://go.hotmart.com/Y4941585Y" target="_blank" rel="noopener">clique aqui e aproveite a promoção especial do Curso de MySQLi</a>.</p>
<p>Você vai aprender a realizar as principais operações com bancos de dados, de forma simples, organizada e otimizada.</p>
<p><a href="https://go.hotmart.com/Y4941585Y" target="_blank" rel="noopener">Clique aqui e conheça o Curso de MySQLi</a></p>

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Guia Completo Passo-a-Passo</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/cover-3d-400x690.png" alt="Guia de migração MySQL para MySQLi" width="180">
</div>

<div class="uphp_cta_text">
	<p>Aprenda <strong>passo-a-passo</strong> como migrar de MySQL para MySQLi</p>
    
    <p>Equivalência entre funções com exemplos práticos de uso!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia e não fique com scripts obsoletos!</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/como-atualizar-php-mysql-mysqli/">Como Atualizar Scripts PHP de MySQL Para MySQLi</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/como-atualizar-php-mysql-mysqli/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1566</post-id>	</item>
		<item>
		<title>Como usar PDO com banco de dados MySQL</title>
		<link>http://rberaldo.com.br/pdo-mysql/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=pdo-mysql</link>
					<comments>http://rberaldo.com.br/pdo-mysql/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Thu, 10 Sep 2015 20:20:12 +0000</pubDate>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[pdo]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1529</guid>

					<description><![CDATA[<p>Como a extensão mysql está obsoleta, é recomendado o uso da extensão PDO. Nesse tutorial, mostro como usar, de forma fácil e clara, PDO com MySQL</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/pdo-mysql/">Como usar PDO com banco de dados MySQL</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter size-full wp-image-1530" src="http://rberaldo.com.br/wp-content/uploads/2015/09/pdo-mysql.jpg" alt="Como usar PDO com banco de dados MySQL" width="484" height="252" srcset="http://rberaldo.com.br/wp-content/uploads/2015/09/pdo-mysql.jpg 484w, http://rberaldo.com.br/wp-content/uploads/2015/09/pdo-mysql-150x78.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/09/pdo-mysql-300x156.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/09/pdo-mysql-96x50.jpg 96w" sizes="(max-width: 484px) 100vw, 484px" /></p>
<p>A partir do PHP 5.5, a biblioteca MySQL, do PHP, com funções como <code>mysql_connect</code> e <code>mysql_query</code> é considerada obsoleta. <a title="MySQL: por que não utilizar funções mysql_*" href="http://rberaldo.com.br/mysql-obsoleto-php/" target="_blank">Falei sobre isso neste post</a>. A alternativa mais recomendada é usar a extensão <a title="Veja a Documentação oficial do PDO" href="http://php.net/manual/pt_BR/book.pdo.php" target="_blank">PDO</a>.</p>
<p>Porém muitos programadores ainda não sabem como usar PDO. Vou mostrar neste post como é simples usar essa classe.</p>
<p><span id="more-1529"></span></p>
<p>É muito importante usar PDO, por duas razões em especial:</p>
<ol>
<li>Seu código fica mais limpo e moderno</li>
<li>É fácil migrar para outro <a title="Artigo da Wikipedia sobre SGBD" href="http://pt.wikipedia.org/wiki/Sistema_de_gerenciamento_de_banco_de_dados" target="_blank">SGBD</a>, caso seja necessário futurament</li>
</ol>
<p>Mas, se você leu <a title="MySQL: por que não utilizar funções mysql_*" href="http://rberaldo.com.br/mysql-obsoleto-php/" target="_blank">este meu post</a>, já deve saber disso.</p>
<h2>O que é PDO</h2>
<p>PDO significa <em>PHP Data Objects</em> (Objetos de Dados do PHP, em tradução livre). Ela é uma classe para gerenciar conexões com bancos de dados. Sim, banco<span style="color: #ff0000;"><strong>s</strong></span> de dados. Ou seja, é possível usar PDO para conectar com diversos <a href="http://pt.wikipedia.org/wiki/Sistema_de_gerenciamento_de_banco_de_dados" target="_blank">SGBDs</a>, dentre eles MySQL, PostreSQL, SQLite, MS SQL Server, Oracle e outros.</p>
<h2>PDO é Orientado a Objetos</h2>
<p>PDO é uma classe. Ela segue o padrão da <a title="Artigo sobre Orientação a Objetos na Wikipedia" href="http://pt.wikipedia.org/wiki/Orientação_a_objetos" target="_blank">Orientação a Objetos</a>. Caso você não conheça absoluutamente nada sobre Orientação a Objetos, recomendo estudar um pouco sobre isso antes de usar PDO.</p>
<p>Não precisa ir muito a fundo. Apenas entenda o que são classes, objetos e métodos. Veja como instanciar objetos e chamar seus métodos. Isso já é suficiente para trabalhar com PDO.</p>
<p>Recomendo ler estes links:</p>
<ul>
<li><a href="http://wbruno.com.br/php/exemplo-pratico-de-orientacao-objetos-php-diferencas-vantagens-em-relacao-a-um-codigo-estruturado" target="_blank">Exemplo prático de Orientação a Objetos (php), diferenças e vantagens em relação à um código Estruturado</a></li>
<li><a href="http://www.devmedia.com.br/introducao-a-orientacao-a-objetos-em-php/26762" target="_blank">Introdução à Orientação a Objetos em PHP</a></li>
</ul>
<h2>Tabela usada para este tutorial</h2>
<p>Criei uma tabela chamada &#8220;programadores&#8221;, com ID, nome e site de cada um deles. Utilizei a seguinte SQL para gerar a tabela e seus dados</p>
<pre lang="sql">CREATE TABLE programadores(
    id int unsigned not null auto_increment,
    nome varchar(80) not null,
    site varchar(120) default null,
    PRIMARY KEY(id)
);

INSERT INTO programadores(nome, site) VALUES
('Beraldo', 'http://rberaldo.com.br'),
('João', NULL),
('Maria', 'http://mariaprogramadora.com.br'),
('José', 'http://joseprogramador.com.br'),
('Linus Torvalds', 'http://kernel.org'),
('Mark Zuckerberg', 'http://facebook.com'),
('Steve Wozniak', 'http://apple.com');
</pre>
<h2>Conexão com MySQL usando PDO</h2>
<p>Vamos definir constantes para armazenar os dados de conexão.</p>
<pre lang="php">define( 'MYSQL_HOST', 'localhost' );
define( 'MYSQL_USER', 'root' );
define( 'MYSQL_PASSWORD', '' );
define( 'MYSQL_DB_NAME', 'pdo_tutorial' );
</pre>
<p>&nbsp;</p>
<p>A conexão é feita pelo construtor da classe PDO. Ou seja, basta passarmos os dados de conexão como parâmetro, ao instanciarmos a classe PDO, desta forma:</p>
<pre lang="php">$PDO = new PDO( 'mysql:host=' . MYSQL_HOST . ';dbname=' . MYSQL_DB_NAME, MYSQL_USER, MYSQL_PASSWORD );
</pre>
<p>Isso funciona. Mas, caso a conexão falhe, será disparada uma exceção e a execução será interrompida.</p>
<p>Para evitarmos isso, devemos colcoar esse trecho em um bloco <code>try...catch</code> e tratar a exceção <code>PDOException</code>. O código ficará assim:</p>
<pre lang="php">try
{
    $PDO = new PDO( 'mysql:host=' . MYSQL_HOST . ';dbname=' . MYSQL_DB_NAME, MYSQL_USER, MYSQL_PASSWORD );
}
catch ( PDOException $e )
{
    echo 'Erro ao conectar com o MySQL: ' . $e->getMessage();
}
</pre>
<h2>Definindo a Codificação UTF-8</h2>
<p>Para definir a codificação UTF-8 (ou outra codificação, caso você ainda não esteja usando UTF-8), basta executar a query abaixo logo após abrir a conexão:</p>
<pre lang="php">
$PDO->exec("set names utf8");
</pre>
<h2>Executando SELECT com PDO</h2>
<p>Tendo a instância da classe PDO na variável <code>$PDO</code>, podemos realizar um simples SELECT desta forma:</p>
<pre lang="php">$sql = "SELECT * FROM programadores";
$result = $PDO->query( $sql );
$rows = $result->fetchAll();

print_r( $rows );
</pre>
<p>O método <code>query</code> da classe <code>PDO</code> executa uma consulta e retorna, no caso do SELECT, um objeto do tipo <code>PDOStatement</code>. Esse objeto possui o método <code>fetchAll</code>, que é semelhante à função <code>mysql_fetch_array</code>, retornando um array com todos os registros. Usamos a função <code>print_r</code> para exibir esse array. A saída é a seguinte:</p>
<pre lang="plain">Array
(
    [0] => Array
        (
            [id] => 1
            [0] => 1
            [nome] => Beraldo
            [1] => Beraldo
            [site] => http://rberaldo.com.br
            [2] => http://rberaldo.com.br
        )

    [1] => Array
        (
            [id] => 2
            [0] => 2
            [nome] => João
            [1] => João
            [site] => 
            [2] => 
        )

    [2] => Array
        (
            [id] => 3
            [0] => 3
            [nome] => Maria
            [1] => Maria
            [site] => http://mariaprogramadora.com.br
            [2] => http://mariaprogramadora.com.br
        )

    [3] => Array
        (
            [id] => 4
            [0] => 4
            [nome] => José
            [1] => José
            [site] => http://joseprogramador.com.br
            [2] => http://joseprogramador.com.br
        )

    [4] => Array
        (
            [id] => 5
            [0] => 5
            [nome] => Linus Torvalds
            [1] => Linus Torvalds
            [site] => http://kernel.org
            [2] => http://kernel.org
        )

    [5] => Array
        (
            [id] => 6
            [0] => 6
            [nome] => Mark Zuckerberg
            [1] => Mark Zuckerberg
            [site] => http://facebook.com
            [2] => http://facebook.com
        )

    [6] => Array
        (
            [id] => 7
            [0] => 7
            [nome] => Steve Wozniak
            [1] => Steve Wozniak
            [site] => http://apple.com
            [2] => http://apple.com
        )

)
</pre>
<p>Note que, para cada registro, há valores repetidos. Eles aparecem em dois índices: um é o número do campo na tabela e o outro é o nom do campo. Isso ocupa o <strong>dobro</strong> da memória. Por isso é recomendado retornar apenas o registro com o nome do campo.</p>
<p>Para isso, basta passarmos o parâmetro <code>PDO::FETCH_ASSOC </code>para o método <code>fetchAll</code>. Dessa forma, esse método funcionará de forma semelhante à função <code>mysql_fetch_assoc</code> retornando apenas o array associativo com os nomes dos campos.</p>
<p>Vamos alterar apenas a linha que chama o método <code>fetchAll</code>. Ela ficará assim:</p>
<pre lang="php">$rows = $result->fetchAll( PDO::FETCH_ASSOC );
</pre>
<p>O array exibido será este:</p>
<pre lang="plain">Array
(
    [0] => Array
        (
            [id] => 1
            [nome] => Beraldo
            [site] => http://rberaldo.com.br
        )

    [1] => Array
        (
            [id] => 2
            [nome] => João
            [site] => 
        )

    [2] => Array
        (
            [id] => 3
            [nome] => Maria
            [site] => http://mariaprogramadora.com.br
        )

    [3] => Array
        (
            [id] => 4
            [nome] => José
            [site] => http://joseprogramador.com.br
        )

    [4] => Array
        (
            [id] => 5
            [nome] => Linus Torvalds
            [site] => http://kernel.org
        )

    [5] => Array
        (
            [id] => 6
            [nome] => Mark Zuckerberg
            [site] => http://facebook.com
        )

    [6] => Array
        (
            [id] => 7
            [nome] => Steve Wozniak
            [site] => http://apple.com
        )

)
</pre>
<h2>Filtrando consultas</h2>
<p>Geralmente, nossos SELECTs possuem a cláusula WHERE, para filtrar os resultados.</p>
<p>Isso é muito fáicl de fazer usando PDO.</p>
<p>Vamos considerar a situação seguinte: vamos solicitar, por meio de um formulário, que o usuário defina uma string para usar no filtro do SELECT. A filtragem será feita pelo campo <code>site</code> da nossa tabela.</p>
<pre lang="php">$search = $_GET['search'];
$sql = "SELECT * FROM programadores WHERE site LIKE '%" . $search . "%'";
$result = $PDO->query( $sql );
$rows = $result->fetchAll( PDO::FETCH_ASSOC );
</pre>
<p>Vamos supor que o usuário digitou a palavra &#8220;programador&#8221;. Logo, <code>$_GET['search']</code> será a string &#8220;programador&#8221;.</p>
<p>O array <code>$rows</code> será este:</p>
<pre lang="plain">Array
(
    [0] => Array
        (
            [id] => 3
            [nome] => Maria
            [site] => http://mariaprogramadora.com.br
        )

    [1] => Array
        (
            [id] => 4
            [nome] => José
            [site] => http://joseprogramador.com.br
        )

)
</pre>
<p>Mas existe uma forma mais eficiente e segura de passar parâmetros para as consultas: usando <a title="Documentação do PHP sobre Prepared Statements no MySQL" href="http://php.net/manual/pt_BR/mysqli.quickstart.prepared-statements.php" target="_blank"><em>Prepared Statements</em></a>.</p>
<h2>O que são Prepared Statements e como usá-los</h2>
<p><a title="Documentação do PHP sobre Prepared Statements no MySQL" href="http://php.net/manual/pt_BR/mysqli.quickstart.prepared-statements.php" target="_blank">Prepared Statements</a> são úteis para executar uma mesma consulta diversas vezes, com parâmetros distintos, de forma eficiente.</p>
<p>Porém também há outra utilidade: filtragem nativa de consultas, a fim de evitar <a title="Proteção Contra SQL Injection" href="http://rberaldo.com.br/seguranca-em-sistemas-de-login-protecao-contra-sql-injection/" target="_blank"><em>SQL Injection</em></a>. Isso dá mais <strong>segurança</strong> ao seu sistema.</p>
<p>Nesse tipo de consulta, os parâmetros não são enviados diretamente na consulta. Eles são enviados em um &#8220;pacote&#8221; separado ao servidor MySQL. O servidor, por sua vez, é quem faz a associação entre string SQL e parâmetros.</p>
<p>Em outras palavras, não vamos colocar a variável $search diretamente na consulta.</p>
<p>Nosso código, usando Prepared Statements, ficará assim:</p>
<pre lang="php">$search = $_GET['search'];
$search = '%' . $search . '%';
$sql = "SELECT * FROM programadores WHERE site LIKE :search";
$stmt = $PDO->prepare( $sql );
$stmt->bindParam( ':search', $search );
$result = $stmt->execute();
</pre>
<p>Veja que nossa query agora possui apenas o valor &#8220;<code>:search</code>&#8221; na cláusula WHERE. É assim que a consulta chegará para o MySQL. Com o método <code>bindParam</code> nós dizemos que queremos enviar o valor de <code>$search</code>, que será substituído em <code>:search</code>.</p>
<p>Como estamos usando o LIKE, tivemos que adicionar os sinais de percentual (%), na segunda linha, manualmente. Se estivéssemos buscando por strings exatas (com o operador <code>=</code>), não precisaríamos disso.</p>
<p>O array <code>$row</code> será o mesmo do código anterior.</p>
<p>Usando Prepared Statements, seu código estará muito mais <strong>seguro</strong>.</p>
<p>E é possível definir o tipo do dado, passando o terceiro parâmetro de bindParam. Os valores possíveis são:</p>
<ul>
<li>PDO::PARAM_BOOL</li>
<li>PDO::PARAM_NULL</li>
<li>PDO::PARAM_INT</li>
<li>PDO::PARAM_STR (esse é o valor padrão)</li>
<li>PDO::PARAM_LOB</li>
</ul>
<p>Esses parâmetros dizem para o MySQL como cada valor deve ser tratado.</p>
<p>Por exemplo, strings devem receber aspas simples ao seu redor. Por outro lado, inteiros não. Por isso é importante passar esses parâmetros, quando o valor não for string.</p>
<h2>INSERT, DELETE e UPDATE usando PDO</h2>
<p>Esses três comandos serão tratados de forma semelhante.</p>
<p>Vejamos como fazer um INSERT.</p>
<pre lang="php">$nome = 'Bill Gates';
$site = 'http://microsoft.com';
$sql = "INSERT INTO programadores(nome, site) VALUES(:nome, :site)";
$stmt = $PDO->prepare( $sql );
$stmt->bindParam( ':nome', $nome );
$stmt->bindParam( ':site', $site );

$result = $stmt->execute();

if ( ! $result )
{
    var_dump( $stmt->errorInfo() );
    exit;
}

echo $stmt->rowCount() . "linhas inseridas";
</pre>
<p>Vamos considerar que <code>$none</code> e <code>site</code> vêm de um formulário também. Por isso precisamos filtrar esses valores usando Prepared Statements.</p>
<p>Para o UPDATE, vamos considerar que desejamos alterar o valor de <code>site</code> para o nome &#8220;Bill Gates&#8221;. O código é o seguinte:</p>
<pre lang="php">$nome = 'Bill Gates';
$site = 'http://ruindows.com.br';
$sql = "UPDATE programadores set site = :site WHERE nome = :nome";
$stmt = $PDO->prepare( $sql );
$stmt->bindParam( ':nome', $nome );
$stmt->bindParam( ':site', $site );

$result = $stmt->execute();

if ( ! $result )
{
    var_dump( $stmt->errorInfo() );
    exit;
}

echo $stmt->rowCount() . "linhas alteradas";
</pre>
<p>Já o DELETE ficará assim:</p>
<pre lang="php">$nome = 'Bill Gates';
$sql = "DELETE FROM programadores WHERE nome = :nome";
$stmt = $PDO->prepare( $sql );
$stmt->bindParam( ':nome', $nome );

$result = $stmt->execute();

if ( ! $result )
{
    var_dump( $stmt->errorInfo() );
    exit;
}

echo $stmt->rowCount() . "linhas removidas";
</pre>
<h2>Conclusão</h2>
<p>Espero que tenha achado útil este tutorial. Há muitos outros recursos da extensão PDO. Você pode ler todos eles na <a href="http://php.net/manual/pt_BR/book.pdo.php" target="_blank">Documentação Oficial da Extensão PDO</a>.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/pdo-mysql/">Como usar PDO com banco de dados MySQL</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/pdo-mysql/feed/</wfw:commentRss>
			<slash:comments>33</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1529</post-id>	</item>
		<item>
		<title>MySQL obsoleto? Entenda Exatamente o Que Fazer</title>
		<link>http://rberaldo.com.br/mysql-obsoleto-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=mysql-obsoleto-php</link>
					<comments>http://rberaldo.com.br/mysql-obsoleto-php/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Thu, 10 Sep 2015 18:54:42 +0000</pubDate>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[obsoleto]]></category>
		<category><![CDATA[php7]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1524</guid>

					<description><![CDATA[<p>Com o MySQL obsoleto a partir do PHP 5.5, funções mysql_*, como mysql_connect e mysql_query devem ser evitadas. Conheça aqui duas alternativas</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/mysql-obsoleto-php/">MySQL obsoleto? Entenda Exatamente o Que Fazer</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter size-full wp-image-1525" src="http://rberaldo.com.br/wp-content/uploads/2015/09/mysql-php-logos.png" alt="MySQL obsoleto: não utilize funções mysql_*" width="500" height="270" srcset="http://rberaldo.com.br/wp-content/uploads/2015/09/mysql-php-logos.png 500w, http://rberaldo.com.br/wp-content/uploads/2015/09/mysql-php-logos-150x81.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/09/mysql-php-logos-300x162.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/09/mysql-php-logos-93x50.png 93w" sizes="(max-width: 500px) 100vw, 500px" /></p>
<p>&nbsp;</p>
<p>Você viu esta mensagem de erro?</p>
<blockquote><p>PHP Deprecated: mysql_connect(): The mysql extension is deprecated and will be removed in the future: use mysqli or PDO instead</p></blockquote>
<p>Aí você me pergunta&#8230;</p>
<blockquote><p>MySQL obsoleto? Então não posso mais usá-lo?</p></blockquote>
<p>Não é bem assim. Estamos falando apenas da <strong>extensão mysql</strong>. E eu vou te mostrar aqui exatamente o que fazer para resolver esse problema e evitar que seus scripts parem de funcionar com o PHP 7 (previsto para ser lançado até meados de dezembro de 2015).</p>
<p>O SGBD MySQL é um dos mais utilizados com a linguagem PHP. Grande parte dos sistemas populares feitos em <a href="http://www.ultimatephp.com.br">PHP</a> utilizam (ou pelo menos suportam) o SGBD MySQL.</p>
<p>Assim como o <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/">PHP</a>, o MySQL também evolui bastante e ganhou novas funcionalidades nos úlitmos anos. Isso fez com que a equipe do PHP desenvolvesse uma nova biblioteca para trabalhar com essas novidades de forma mais efetiva. Essa nova biblioteca foi chamada de <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank">MySQLi</a> (o &#8220;i&#8221; do final refere-se a &#8220;<em>improved</em>&#8220;, que significa &#8220;melhorada&#8221;).</p>
<p><span id="more-1524"></span></p>
<h2>MySQL obsoleto Vs Extensão MySQL Obsoleta</h2>
<p>O MySQL é o SGBD em si. Não é dele exatamente que estou falando. Estou falando da <strong>extensão mysql</strong> (ou <strong>biblioteca mysql</strong>) do PHP.</p>
<p>A bibliteca MySQL, que conta com funções como <strong>mysql_connect</strong>, <strong>mysql_query</strong> e semelhantes, não permite utilizar recursos novos do MySQL, como <em>triggers</em>, <em>stored procedures</em> e outros. Esses recursos só estão disponíveis com o uso da biblioteca <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank">MySQLi</a>.</p>
<p>A extensão MySQLi existe desde o PHP 5.0, que foi lançado em 13 de julho 2004. Desde então, já era recomendado usar MySQLi em vez de MySQL.</p>
<p>Porém muitos programadores continuaram usando, ainda usam até hoje, a biblioteca MySQL.</p>
<p>Para mudar esse cenário, a equipe do PHP tomou uma atitude um tanto drástica: removeram a biblioteca MySQL do <a href="http://cursophp7.ultimatephp.com.br" target="_blank">PHP 7</a>.</p>
<p>Mas calma! Não entre em desespero!</p>
<h2>Extensão MySQL obsoleta</h2>
<p><a title="Veja a lista de recursos oboletos a partir do PHP 5.5" href="http://php.net/manual/pt_BR/migration55.deprecated.php" target="_blank">A partir do PHP 5.5, a biblioteca MySQL é considerada obsoleta</a>, mas ainda funciona. Porém, é recomendado não utilizá-la mais, pois já foi removida do PHP 7, que deve ser lançada até o final de 2015.</p>
<h2>Isso Foi Uma Atitude Drástica?</h2>
<p>Muitos acham um absurdo a equipe do PHP ter ternado a biblioteca MySQL obsoleta no PHP 5.5. Mas vamos analisar melhor.</p>
<p>Como eu disse antes, a extensão <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank">MySQLi</a> foi lançada junto com o PHP 5.0, em 13 de julho 2004. Desde então, a comunidade do PHP sugere utilizar essa biblioteca em vez do MySQL.</p>
<p>Poucos programadores aderiram à ideia.</p>
<p>Conclusão da equipe do PHP: vamos forçá-los a migrar para o MySQLi.</p>
<p>A versão 5.5.0 foi lançada em 20 de junho 2013, ou seja, <strong>NOVE ANOS</strong> após a publicação do PHP 5.0 e as recomendações do uso do MySQLi.</p>
<p>Estamos em 2015 (quando escrevo este artigo) e ainda tem gente usando MySQL.</p>
<p>Já se passaram ONZE ANOS! Por todo esse tempo a comunidade do PHP sugere usar MySQLi.</p>
<p>Ou seja, não acho nada drástica a iniciativa de tornar o MySQL obsoleto. Afinal, muitos só se mexem quando &#8220;a água bate na bunda&#8221;.</p>
<p>Então deixe a preguiça de lado e migre suas aplicações para MySQLi ou PDO agora mesmo!</p>
<blockquote><p>E o que devo fazer, Beraldo??!!</p></blockquote>
<p>[cta id=&#8217;1571&#8242;]</p>
<h2 style="margin-top: -2em;">Alternativas à extensão MySQL</h2>
<ol>
<li>Usar a extensão <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank">MySQLi</a> em vez da MySQL</li>
<li>Usar a extensão <a href="http://rberaldo.com.br/pdo-mysql/" target="_blank">PDO</a> (<em>PHP Data Object</em>)</li>
</ol>
<blockquote><p>E qual devo escolher, Beraldo?</p></blockquote>
<p>A extendão <a href="http://www.ultimatephp.com.br/guia-atualizacao-mysql-mysqli/" target="_blank">MySQLi</a> lhe dará tudo o que você já tem hoje com a extensão MySQL. Além disso, você terá acesso aos novos recursos do MySQL. Também estará usando uma bilioteca mais recente.</p>
<p>Mas a extensão <a href="http://rberaldo.com.br/pdo-mysql/" target="_blank">PDO</a> tem uma grande vantagem.</p>
<p>PDO é uma camada de abstração de banco de dados. O nome assusta, mas é simples: ela é um interface genérica para diveroso SGBDs. Ou seja, seu código escrito com PDO funcionará com MySQL, PostgreSQL, SQLite e diversos outros SGBDs.</p>
<p>A vantagem disso é que, se um dia precisar trocar o SGBD, terá de fazer pouquíssimas alterações no código.</p>
<p>Nunca se sabe o dia de amanhã. Talvez sua aplicação cresça muito e precise trocar o SGBD. Então, se o <a href="http://www.ultimatephp.com.br">PHP</a> já nos dá esse recurso de brinde, vale a pena utilizá-lo! :)</p>
<p><a title="Como usar PDO com banco de dados MySQL" href="http://rberaldo.com.br/pdo-mysql/">Veja aqui</a> um tutorial sobre como usar PDO com MySQL.</p>
<p>Mas eu sei que muitos iniciantes têm dificuldade com Orientação a Objetos e por isso acham PDO difícil. Por isso eu criei <a href="http://rberaldo.com.br/como-atualizar-php-mysql-mysqli/" target="_blank">este artigo</a>, onde mostro como usar MySQLi sem precisar usar Orientação a Objetos.</p>
<h2>Outras Novidades do PHP 7</h2>
<p>O PHP 7 deve ser lançado oficialmente até o final de 2015. Mas a versão RC está disponível desde o final de agosto.</p>
<p>Então já podemos ter uma ideia do que está por vir.</p>
<p>Além do fim do MySQL, há diversas outras ótimas novidades, como sua incrível velocidade, sendo <a href="http://rberaldo.com.br/php-7-9-vezes-mais-rapido-que-php-5-6/" target="_blank">até NOVE vezes mais rápido que o PHP 5.6</a>.</p>
<p>Para aprender todas as novidades, inscreva-se no meu <a href="http://cursophp7.ultimatephp.com.br" target="_blank">curso 100% GRATUITO sobre o PHP 7</a>.</p>
<p><strong><a href="http://cursophp7.ultimatephp.com.br" target="_blank">CLIQUE AQUI Para Se Inscrever No Meu Curso Gratuito Sobre o PHP 7</a></strong></p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/mysql-obsoleto-php/">MySQL obsoleto? Entenda Exatamente o Que Fazer</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/mysql-obsoleto-php/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1524</post-id>	</item>
		<item>
		<title>PHP 7: Até 9 Vezes Mais Rápido Que o PHP 5.6</title>
		<link>http://rberaldo.com.br/php-7-9-vezes-mais-rapido-que-php-5-6/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=php-7-9-vezes-mais-rapido-que-php-5-6</link>
					<comments>http://rberaldo.com.br/php-7-9-vezes-mais-rapido-que-php-5-6/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Sat, 05 Sep 2015 12:31:48 +0000</pubDate>
				<category><![CDATA[Programação]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1508</guid>

					<description><![CDATA[<p>O PHP 7 (sucessor do PHP 5.6) se demonstra muito mais rápido que suas versões anteriores. Em alguns casos, pode ser até 9 vezes (NOVE!!) mais rápido! Veja aqui os resultados do testes que fiz comparando o PHP 5.6 e o PHP 7. Você vai se surpreender! E também tenho uma surpresa, que vou revelar [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/php-7-9-vezes-mais-rapido-que-php-5-6/">PHP 7: Até 9 Vezes Mais Rápido Que o PHP 5.6</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1517 size-full" src="http://rberaldo.com.br/wp-content/uploads/2015/09/image-01.png" alt="PHP 7: Até 9 Vezes Mais Rápido Que o PHP 5.6" width="560" height="292" srcset="http://rberaldo.com.br/wp-content/uploads/2015/09/image-01.png 560w, http://rberaldo.com.br/wp-content/uploads/2015/09/image-01-150x78.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/09/image-01-300x156.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/09/image-01-96x50.png 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>O PHP 7 (sucessor do PHP 5.6) se demonstra muito mais rápido que suas versões anteriores. Em alguns casos, pode ser até 9 vezes (NOVE!!) mais rápido!</p>
<p>Veja aqui os resultados do testes que fiz comparando o PHP 5.6 e o PHP 7. Você vai se surpreender!</p>
<p>E também tenho uma <strong>surpresa</strong>, que vou revelar no final do artigo. Mas não vale ir direto pra lá, heim?! :P</p>
<p><span id="more-1508"></span></p>
<h2>O PHP 7</h2>
<p>O PHP 7 é o sucessor do PHP 5. Não existiu versão pública do PHP 6 por alguns motivos.</p>
<p>Houve um PHP 6. Ou pelo menos uma tentativa dele. Porém o resultado não foi satisfatório e a versão não foi publicada oficialmente, mas existiram informações sobre essa versão. Logo poderia haver confusão se esta nova versão se chamasse PHP 6.</p>
<p>Outro motivo é que tinha muito <strong>charlatão</strong> por aí vendendo livros, cursos e aulas sobre o PHP 6, que nem sequer existia oficialmente.</p>
<p>Então, para evitar esses problemas, a equipe do PHP resolveu chamar a nova versão de PHP 7.</p>
<p>Se quiser ler os diversos motivos dessa escolha, leia o <a href="https://wiki.php.net/rfc/php6" target="_blank">RFC oficial sobre a discussão sobre o nome da versão do PHP</a>.</p>
<p>A versão <em>Release Candidate</em> (RC) do PHP 7 <a href="http://php.net/archive/2015.php#id2015-08-21-1" target="_blank">foi lançada no dia 21 de agosto</a>. Por ser uma versão RC, é bem provável que haja pouquíssimas mudanças até a versão final. Apenas algumas correções de <em>bugs</em>.</p>
<p>Isso quer dizer que os resultados que obtivermos agora serão bem próximos (ou até iguais) aos que teremos com a versão final.</p>
<h2>Critério de Comparação</h2>
<p>Para comparar o desempenho, utilizei o script de benchmark que o próprio PHP traz. No código-fonte do PHP no GitHub, encontramos o <a href="https://github.com/php/php-src/blob/master/Zend/bench.php" target="_blank">arquivo <code>Zend/bench.php</code></a>, que é o script responsável por analisar o desempenho, executando algumas rotinas comuns.</p>
<p>Esse é o script que utilizarei para analisar o desempenho das versões do PHP.</p>
<p>Ao executar o script, você verá uma lista de execuções e seus respectivos tempos. No final, será exibido o tempo total. É esse tempo total que nos interessa aqui.</p>
<p>Veja um exemplo da execução:</p>
<pre lang="bash">php Zend/bench.php 
simple             0.395
simplecall         0.954
simpleucall        1.063
simpleudcall       1.073
mandel             1.027
mandel2            1.072
ackermann(7)       0.821
ary(50000)         0.041
ary2(50000)        0.029
ary3(2000)         0.563
fibo(30)           2.911
hash1(50000)       0.145
hash2(500)         0.049
heapsort(20000)    0.265
matrix(20)         0.245
nestedloop(12)     0.703
sieve(30)          0.244
strcat(200000)     0.035
------------------------
Total             11.635
</pre>
<p>Como o tempo de execução pode variar um pouco, o correto é executar algumas vezes e fazer a média.</p>
<p>Vou executar o script 15 vezes com cada versão do PHP.</p>
<h2>Script Utilizado</h2>
<p>Para agilizar a tarefa de executar 15 vezes e fazer a média, vou usar um pequeno Shell Script. Basicamente um loop e alguns echo&#8217;s. Vou dividir o comando em linhas para facilitar a visualização:</p>
<pre lang="bash">soma=0; \
for ((i = 0; i < 15; i++)) ; \
do \
    tempo=$(php Zend/bench.php | tail -n 1 | awk '{print $2}'); \
    echo "Tempo $i: $tempo"; \
    soma=$(echo "$soma + $tempo" | bc -l); \
done ; \
echo "Tempo total: $soma"; \
media=$(echo "scale=3; $soma / $i" | bc -l); \
echo "Tempo médio: $media"
</pre>
<p>O script <code>Zend/bench.php</code> será executado no próprio terminal. Caso você nunca tenha visto isso antes, recomendo ler <a href="http://rberaldo.com.br/diferentes-formas-execucao-php/" target="_blank">este meu artigo, onde mostro as diferentes formas de execução do PHP</a>.</p>
<p>Caso você queira entender melhor como os scripts Shell funcionam, <a href="http://rberaldo.com.br/curso-de-shell-script-modulo-1-scripts-shell-estruturas/" target="_blank">veja este meu mini-curso gratuito de Shell Script</a>.</p>
<h2>Plataforma</h2>
<p>Fiz os testes na seguinte plataforma:</p>
<ul>
<li>Processador: Intel Core i7 2,6 GHz</li>
<li>Memória: 16 GB DDR3 1600 MHz</li>
<li>Sistema operacional: Mac OS X 10.10.4 (Yosemite)</li>
</ul>
<p>As versões do PHP usadas foram 5.6.12 e 7.0RC1.</p>
<h2>Resultados</h2>
<p>Na tabela abaixo mostro os resultados das 15 execuções e o tempo médio para cada versão do PHP.</p>
<table>
<thead>
<tr>
<th></th>
<th>PHP 5.6.12</th>
<th>PHP 7.0RC1</th>
</tr>
</thead>
<tbody>
<tr>
<td>Execução 01</td>
<td>11.246</td>
<td>1.233</td>
</tr>
<tr>
<td>Execução 02</td>
<td>11.858</td>
<td>1.179</td>
</tr>
<tr>
<td>Execução 03</td>
<td>12.045</td>
<td>1.185</td>
</tr>
<tr>
<td>Execução 04</td>
<td>11.793</td>
<td>1.239</td>
</tr>
<tr>
<td>Execução 05</td>
<td>11.733</td>
<td>1.195</td>
</tr>
<tr>
<td>Execução 06</td>
<td>11.898</td>
<td>1.233</td>
</tr>
<tr>
<td>Execução 07</td>
<td>11.885</td>
<td>1.202</td>
</tr>
<tr>
<td>Execução 08</td>
<td>11.877</td>
<td>1.205</td>
</tr>
<tr>
<td>Execução 09</td>
<td>11.901</td>
<td>1.227</td>
</tr>
<tr>
<td>Execução 10</td>
<td>11.885</td>
<td>1.210</td>
</tr>
<tr>
<td>Execução 11</td>
<td>11.844</td>
<td>1.343</td>
</tr>
<tr>
<td>Execução 12</td>
<td>11.842</td>
<td>1.325</td>
</tr>
<tr>
<td>Execução 13</td>
<td>12.070</td>
<td>1.305</td>
</tr>
<tr>
<td>Execução 14</td>
<td>11.698</td>
<td>1.178</td>
</tr>
<tr>
<td>Execução 15</td>
<td>11.768</td>
<td>1.327</td>
</tr>
<tr>
<td>Tempo Total</td>
<td>177.343</td>
<td>18.586</td>
</tr>
<tr>
<td>Tempo Médio</td>
<td>11.822</td>
<td>1.239</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p>Para visualizar melhor as diferenças de tempo, montei estes dois gráficos</p>
<p><img loading="lazy" class="aligncenter size-full wp-image-1511" src="http://rberaldo.com.br/wp-content/uploads/2015/09/execucoes.png" alt="execucoes" width="420" height="307" srcset="http://rberaldo.com.br/wp-content/uploads/2015/09/execucoes.png 420w, http://rberaldo.com.br/wp-content/uploads/2015/09/execucoes-150x110.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/09/execucoes-300x219.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/09/execucoes-68x50.png 68w" sizes="(max-width: 420px) 100vw, 420px" /></p>
<p><img loading="lazy" class="aligncenter size-full wp-image-1512" src="http://rberaldo.com.br/wp-content/uploads/2015/09/media.jpg" alt="media" width="403" height="320" srcset="http://rberaldo.com.br/wp-content/uploads/2015/09/media.jpg 403w, http://rberaldo.com.br/wp-content/uploads/2015/09/media-150x119.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/09/media-300x238.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/09/media-63x50.jpg 63w" sizes="(max-width: 403px) 100vw, 403px" /></p>
<p>Se dividirmos o tempo médio do PHP 5.6 pelo tempo médio do PHP 7, teremos:</p>
<p><span style="font-size: 14pt;"><strong>11.822 / 1.239 = 9.541</strong></span></p>
<p>Ou seja, o PHP 7 se saiu NOVE VEZES MAIS RÁPIDO!</p>
<p>Logicamente, esse número pode variar conforma o hardware e conforme a tarefa executada. Neste caso, analisei somente o benchmark sugerido pelo próprio PHP.</p>
<h2>Conclusão</h2>
<p>O PHP 7 é, de fato, muito mais rápido que o PHP 5.</p>
<p>Resta analisar em casos reais, como em frameworks, CMS etc. Mas apenas com esse teste já vemos que ele tem desempenho bem superior em relação às versões anteriores</p>
<h2>Quer Aprender Mais Sobre o PHP 7?</h2>
<p>Para aprender todas as novidades do PHP 7 e todos os fundamentos essenciais da linguagem, o <a href="http://www.ultimatephp.com.br/curso/" target="_blank">Curso ULTIMATE PHP</a> foi totalmente reformulado e atualizado. O resultado foi o <a href="http://www.ultimatephp.com.br/curso/" target="_blank">ULTIMATE PHP 2.0</a>, o primeiro curso do Brasil a abordar o PHP 7, logo em dezembro de 2015, quando a versão final do PHP 7 foi lançada.</p>
<p>No curso, você aprenderá desde o básico do PHP, vendo todos os conceitos e fundamentos da linguagem, até conceitos de nível intermediário. Alguns temas mais avançados são abordados, como Orientação a Objetos e Segurança.</p>
<p><a href="http://www.ultimatephp.com.br/curso/" target="_blank"><strong style="font-size: 1.3em;">Clique Aqui e Conheça o Curso ULTIMATE PHP</strong></a></p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/php-7-9-vezes-mais-rapido-que-php-5-6/">PHP 7: Até 9 Vezes Mais Rápido Que o PHP 5.6</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/php-7-9-vezes-mais-rapido-que-php-5-6/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1508</post-id>	</item>
		<item>
		<title>DotEnv: O Lugar Perfeito Para as Configurações do Seu Projeto PHP</title>
		<link>http://rberaldo.com.br/dotenv-lugar-perfeito-configuracoes-projeto-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=dotenv-lugar-perfeito-configuracoes-projeto-php</link>
					<comments>http://rberaldo.com.br/dotenv-lugar-perfeito-configuracoes-projeto-php/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Fri, 28 Aug 2015 15:35:23 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Segurança]]></category>
		<category><![CDATA[configuração]]></category>
		<category><![CDATA[dotenv]]></category>
		<category><![CDATA[segurança]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1497</guid>

					<description><![CDATA[<p>Onde você armazena as configurações sensíveis do seu projeto PHP? Se as define diretamente em seu código, você pode estar correndo um enorme risco de Segurança. Configurações como nomes de usuário de banco de dados, senhas de SMTP e outras informações sensíveis devem ficar em um local seguro. E o mais importante: fora do controle [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/dotenv-lugar-perfeito-configuracoes-projeto-php/">DotEnv: O Lugar Perfeito Para as Configurações do Seu Projeto PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1498 size-full" src="http://rberaldo.com.br/wp-content/uploads/2015/08/image.png" alt="DotEnv: O Lugar Perfeito Para as Configurações do Seu Projeto PHP" width="560" height="292" srcset="http://rberaldo.com.br/wp-content/uploads/2015/08/image.png 560w, http://rberaldo.com.br/wp-content/uploads/2015/08/image-150x78.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/08/image-300x156.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/08/image-96x50.png 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>Onde você armazena as configurações sensíveis do seu projeto PHP? Se as define diretamente em seu código, você pode estar correndo um <strong>enorme risco de Segurança</strong>.</p>
<p>Configurações como nomes de usuário de banco de dados, senhas de SMTP e outras informações sensíveis devem ficar em um local seguro. E o mais importante: fora do controle de versão do software (como Git, SVN e outros).</p>
<p>Neste artigo vou mostrar como utilizar o DotEnv de forma extremamente. Com duas linhas de código, todas as configurações importantes de seu projeto estarão disponíveis em variáveis de ambiente.</p>
<p><span id="more-1497"></span></p>
<p>Essa é a ideia do projeto <a href="https://github.com/vlucas/phpdotenv" target="_blank">DotEnv</a>. As configurações sensíveis ficam armazenadas em um arquivo chamado <code>.env</code> (o ponto caracteriza um arquivo oculto em sistemas Unix-Like).</p>
<p>Todas as variáveis definidas no <code>.env</code> são automaticamente carregadas para variáveis de ambiente. Ou seja, para buscar seus valores, podemos usar a função <a href="http://php.net/manual/pt_BR/function.getenv.php" target="_blank"><code>getenv()</code></a> ou o array <a href="http://php.net/manual/pt_BR/reserved.variables.environment.php" target="_blank"><code>$_ENV</code></a>.</p>
<h2>Instalando o DotEnv</h2>
<p>Para instalar o DotEnv, vou utilizar o <a href="http://rberaldo.com.br/composer-php/" target="_blank">Composer</a>. Se você não utiliza Composer, o que está esperando? Veja <a href="http://rberaldo.com.br/composer-php/" target="_blank">este meu artigo</a> com o básico do Composer. Se quiser ir mais além e aprender tudo sobre essa maravilhosa ferramenta, conheça o meu <a href="http://ultimatecomposer.com.br" target="_blank">curso ULTIMATE COMPOSER</a>.</p>
<p>Abra o terminal/prompt, no diretório-raiz da sua aplicação, e digite este comando:</p>
<pre lang="bash">composer require vlucas/phpdotenv
</pre>
<p>Depois de alguns segundos, o DotEnv terá sido completamente baixado e você verá esta saída:</p>
<pre lang="plain">Using version ^2.0 for vlucas/phpdotenv
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing vlucas/phpdotenv (v2.0.1)
    Downloading: 100%         

Writing lock file
Generating autoload files
</pre>
<h2>Criando o Arquivo <code>.env</code></h2>
<p>Você precisa criar, no diretório-raiz do projeto, um arquivo chamado <code>.env</code>, que vai armazenar as variáveis. É importante colocar o ponto no começo, pois isso caracteriza um arquivo oculto, assim como é o <code>.htaccess</code>, por exemplo.</p>
<p>No arquivo, basta definir as variáveis com esta sintaxe:</p>
<pre lang="bash">NOME_DA_VARIAVEL=VALOR_DA_VARIAVEL
</pre>
<p>Esse arquivo segue o mesmo padrão de um arquivo Shell Script. Inclusive, você pode inserir comentários, iniciando a linha com sustenido:</p>
<pre lang="bash"># Explicação sobre a variável
NOME_DA_VARIAVEL=VALOR_DA_VARIAVEL
</pre>
<p>Se você estiver usando controle de versão (como Git ou SVN), lembre-se de não versionar o arquivo <code>.env</code>, por razões de segurança. Coloque-o no <code>.gitignore</code> para garantir que seja ignorado.</p>
<p>É recomendável criar um arquivo chamado <code>.env.example</code>, com as mesmas variáveis do <code>.env</code>, mas com valores genéricos, apenas de exemplo. Dessa forma é fácil criar o arquivo real a partir do exemplo. Bastaria copiar o <code>.env.example</code> para <code>.env</code> e alterar os valores.</p>
<h2>Carregando as Variáveis de Ambiente</h2>
<p>Agora que já temos o DotEnv instalado e o arquivo <code>.env</code> criado, precisamos carregar as variáveis do arquivo para variáveis de ambiente.</p>
<p>E isso é extremamente fácil! Apenas duas linhas!</p>
<p>Crie o arquivo <code>index.php</code> com este conteúdo:</p>
<pre lang="php">
<?php 

// autoload do Composer 
require 'vendor/autoload.php'; 

// as duas linhas que carregam as variáveis do .env para variáveis de ambiente 
$dotenv = new Dotenv\Dotenv( __DIR__ ); 
$dotenv->load();
</pre>
<p>Pronto! Todas as variáveis do arquivo <code>.env</code> agora estarão definidas como variáveis de ambiente.</p>
<p>Você pode confirmar isso desta forma:</p>
<pre lang="php">
print_r( $_ENV );
</pre>
<p>Você verá suas variáveis no array exibido.</p>
<p>Para buscar uma única variável, pode usar o array <code>$_ENV</code> ou a função <code>getenv()</code>:</p>
<pre lang="php">
echo $_ENV['NOME_DA_VARIAVEL'];
// ou
echo getenv( 'NOME_DA_VARIAVEL' );
</pre>
<h2>Conclusão</h2>
<p>O DotEnv é a forma mais segura de armazenar as configurações sensíveis de seu projeto.</p>
<p>Você pode combinar essa técnica com um conceito de <em>Bootstrapping</em>, que explico <a href="http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/" target="_blank">neste artigo</a>. Assim você terá um sistema seguro, rápido e confiável.</p>
<p>No meu <a href="http://www.ultimatephp.com.br/curso/" target="_blank">Curso ULTIMATE PHP</a>, explico diversas outras técnicas e dicas sobre PHP. Ensino desde o básico da linguagem, detalhando toda a teoria essencial, para criar sistemas robustos, confiáveis e seguros. Tudo de forma 100% prática, com exemplos. <a href="http://www.ultimatephp.com.br/curso/" target="_blank">Clique Aqui e Conheça Melhor o Curso</a>.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/dotenv-lugar-perfeito-configuracoes-projeto-php/">DotEnv: O Lugar Perfeito Para as Configurações do Seu Projeto PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/dotenv-lugar-perfeito-configuracoes-projeto-php/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1497</post-id>	</item>
		<item>
		<title>URLs Amigáveis Sem htaccess Usando Slim</title>
		<link>http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=urls-amigaveis-sem-htaccess-usando-slim</link>
					<comments>http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Wed, 24 Jun 2015 17:20:05 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[mod_rewrite]]></category>
		<category><![CDATA[rotas]]></category>
		<category><![CDATA[slim]]></category>
		<category><![CDATA[urls amigáveis]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1451</guid>

					<description><![CDATA[<p>Você já sofreu criando regras malucas no seu .htaccess pra conseguir criar suas URLs Amigáveis? Conhece pouco sobre Expressões Regulares e sempre apanha das regras de reescrita? Já imaginou criar URLs Amigáveis sem essas dores de cabeça, tudo em PHP puro, sem .htaccess, de forma clara e objetiva? E o melhor: em poucos segundos! Há [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/">URLs Amigáveis Sem htaccess Usando Slim</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" src="http://rberaldo.com.br/wp-content/uploads/2015/06/slim-urls-amigaveis-sem-htaccess.png" alt="URLs Amigáveis Sem .htaccess Usando Slim" width="560" height="292" class="aligncenter size-full wp-image-1453" srcset="http://rberaldo.com.br/wp-content/uploads/2015/06/slim-urls-amigaveis-sem-htaccess.png 560w, http://rberaldo.com.br/wp-content/uploads/2015/06/slim-urls-amigaveis-sem-htaccess-150x78.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/06/slim-urls-amigaveis-sem-htaccess-300x156.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/06/slim-urls-amigaveis-sem-htaccess-96x50.png 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>Você já sofreu criando regras malucas no seu <code>.htaccess</code> pra conseguir criar suas URLs Amigáveis?</p>
<p>Conhece pouco sobre Expressões Regulares e sempre apanha das regras de reescrita?</p>
<p>Já imaginou criar URLs Amigáveis sem essas dores de cabeça, tudo em PHP puro, sem <code>.htaccess</code>, de forma clara e objetiva?</p>
<p>E o melhor: em poucos <strong>segundos</strong>!</p>
<p>Há uma maneira muito simples de fazer isso. E a solução se chama <strong>Slim</strong>.</p>
<p>Continue lendo, que você vai ver como criar URLs Amigáveis pode ser uma tarefa <strong>ridiculamente</strong> simples e rápida.</p>
<p><span id="more-1451"></span></p>
<p>Hoje eu quero solucionar um GRANDE problema:</p>
<p><em>Criar URLs Amigáveis Sem <code>.htaccess</code></em></p>
<p>Isso é possível, sim. E o melhor: é extremamente simples!</p>
<p>Vamos usar um pequeno framework, chamado <a href="http://www.slimframework.com" target="_blank">Slim</a>.</p>
<h2>O Que é o Slim</h2>
<p>O <strong>Slim</strong> é um <em>micro-framework</em>. Ou seja, um conjunto pequeno (porém poderoso) de ferramentas para desenvolver aplicações.</p>
<p>Ele permite fazer diversas outras coisas, não apenas criar URLs Amigáveis, também chamadas de <strong>rotas</strong>. Dentre os principais recursos do Slim estão:</p>
<ul>
<li>Rotas (URLs Amigáveis)</li>
<li>Gerenciamento de Requisições HTTP</li>
<li>Gerenciamento de Sessões</li>
<li><em>Cache</em></li>
<li>Criptografia</li>
</ul>
<p>O Slim é bem completo e faz várias coisas, porém hoje vou mostrar apenas a parte de Rotas.</p>
<p>Se vocês gostarem da ferramenta e comentarem aqui no post, farei outros artigos mostrando mais recursos do Slim. :)</p>
<h2>URLs Amigáveis Usando o Slim</h2>
<p>Que tal um desafio?</p>
<p>Vamos criar uma aplicação com URLs Amigáveis <strong>do zero</strong> em apenas <strong>poucos segundos</strong>?</p>
<p>Parece loucura? Impossível?</p>
<p>Não é!</p>
<p>Vou mostrar como é simples.</p>
<p>Para criarmos nosso projeto, vamos usar o <a href="http://rberaldo.com.br/composer-php/" target="_blank">Composer</a>.</p>
<p>Lembrando que o Composer fica instalado <strong>na sua máquina local</strong>. Você pode instalá-lo no seu servidor, mas <strong>não precisa</strong>. Você usará o Composer em sua máquina para baixar o Slim. Depois basta fazer upload de tudo para o servidor (mesmo que o Composer não esteja instalado lá, tudo vai funcionar). </p>
<p>Com o Composer instalado, abra o terminal (prompt de comando, pra quem sofre usando Windows) e digite:</p>
<pre lang="bash">
composer require slim/slim
</pre>
<p>O Composer vai baixar o Slim, além do seu próprio <em>autoloader</em>, que utilizaremos para carregar o Slim em nossa aplicação.</p>
<p>Agora você verá esta estrutura de arquivos</p>
<pre lang="plain">
├── composer.json
├── composer.lock
└── vendor
    ├── autoload.php
    ├── composer
    └── slim
</pre>
<p>Só precisamos criar nosso arquivo <code>index.php</code>. Crie-o com este conteúdo:</p>
<pre lang="php">
<?php
require 'vendor/autoload.php';

/* =================
   Instanciando o Slim
   Escolha uma das opções abaixo. 
   A primeira não exibe os erros, ideal para ambiente de produção
   A segunda exibe erros, ideal para debug em ambiente de desenvolvimento
   ================ */

// Esta linha instancia o Slim, sem habilitar os erros
$app = new \Slim\App();

// Estas linhas instanciam o Slim, habilitando os erros (útil para debug, em desenvolvimento)
$app = new \Slim\App([
    'settings' => [
        'displayErrorDetails' => true
    ]
]);


/* ============
   Rotas da aplicação
   ============ */


$app->get('/', function ()
{
    echo "Página inicial";
});

$app->get('/contato', function ()
{
    echo "Fale conosco";
});

$app->run();
</pre>
<p>Pronto!</p>
<p>Agora basta iniciar o <a href="http://rberaldo.com.br/como-usar-o-servidor-nativo-do-php-5-4/" target="_blank">servidor do PHP</a>:</p>
<pre lang="bash">
php -S localhost:8000
</pre>
<p>Agora acesse as URLs abaixo:</p>
<ul>
<li><strong>http://localhost:8000/</strong></li>
<li><strong>http://localhost:8000/contato</strong></li>
</ul>
<p>Seu projeto com URLs Amigáveis já está funcionando!</p>
<p>Falei que seriam <strong>apenas alguns segundos</strong>!</p>
<h2>Parâmetros de URL</h2>
<p>Provavelmente você ainda não está satisfeito(a), né?</p>
<p>Aí você me diz:</p>
<blockquote><p>
    <em>E se eu quiser passar parâmetros dinâmicos na URL?</em>
</p></blockquote>
<p>É tão simples quanto!</p>
<p>Vamos imaginar que temos um sistema de artigos e que precisamos permitir a exibição de artigos pelo seu ID. Por exemplo, para exibir o artigo de ID 7, usaremos a URL <strong>localhost:8000/artigos/7</strong>.</p>
<p>Nesse caso, o número 7 é a parte dinâmica da URL. </p>
<p>Para montar essa rota, vamos adicionar esta regra ao nosso arquivo <code>index.php</code>:</p>
<pre lang="php">
$app->get('/artigos/{id}', function ( $request )
{
    $id = $request->getAttribute('route')->getArgument('id');
    printf( "Exibindo artigo %d", $id );
});
</pre>
<p>Veja que a rota é <em>artigos/{id}</em>. As chaves entre o <code>id</code> diz que esse valor é um parâmetro, que será passado como parâmetro para a função que manipula essa rota.</p>
<h2>Outros Métodos HTTP</h2>
<p>Nos exemplos anteriores, usamos apenas o método GET para as rotas. Mas também é possível usar os outros métodos HTTP, como POST, PUT, DELETE e outros. Basta trocar o nome do método ao definir a rota:</p>
<pre lang="php">
$app->post('/enviar', function ()
{
    echo "método post";
});

$app->put('/alterar', function ()
{
    echo "método put";
});

$app->delete('/remover', function ()
{
    echo "método delete";
});
</pre>
<p>Logicamente, também é possível usar parâmetros nessas rotas.</p>
<h2>Só Um Pouco de <code>.htaccess</code>&#8230;</h2>
<p>Eu falei que não usaríamos <code>.htaccess</code> para criar as URLs Amigáveis, certo?</p>
<p>E realmente não usamos.</p>
<p>Mas pode ser necessário criar o <code>.htaccess</code> para que todas as requisições seja encaminhadas para o arquivo <code>index.php</code>. Isso garante que suas rotas funcionem adequadamente em qualquer servidor web.</p>
<p>Vamos criar o <code>.htaccess</code> com este conteúdo:</p>
<pre lang="bash">
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</pre>
<p>Apenas dizemos para encaminhar as requisições sempre para nosso <code>index.php</code>.</p>
<h2>Conclusão</h2>
<p>Em apenas alguns segundos, usando o Slim e o Composer, conseguimos criar um sistema de rotas bem completo e fácil de manter.</p>
<p>Esse é só um dos inúmeros excelentes recursos do Slim. Veja algumas outras facilidades que ele possui:</p>
<ul>
<li>Criação de Rotas (URLs Amigáveis). Mostrei o básico aqui, mas há diversos outros recursos mais avançados;</li>
<li>Rotas nomeadas, para facilitar a criação de links e navegação em seu sistema;</li>
<li>Grupos de rotas, permitindo diversos métodos HTTP para a mesma rota;</li>
<li><em>Middlewares</em>, para garantir a Segurança e impedir acesso indevido por usuários não logados;</li>
<li>Gerenciamento de Requisições HTTP, para desenvolver clientes de <em>Web Service</em> com facilidade;</li>
<li>Gerenciamento de Sessões, para facilitar o desenvolvimento de sistemas de login;</li>
<li><em>Cache</em>, para acelerar o carregamento de sua aplicação;</li>
<li>Criptografia, para garantir total Segurança para os dados de seus usuários;</li>
</ul>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/">URLs Amigáveis Sem htaccess Usando Slim</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/feed/</wfw:commentRss>
			<slash:comments>27</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1451</post-id>	</item>
		<item>
		<title>Composer: o gerenciador de dependências para PHP</title>
		<link>http://rberaldo.com.br/composer-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=composer-php</link>
					<comments>http://rberaldo.com.br/composer-php/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Thu, 11 Jun 2015 21:48:53 +0000</pubDate>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[composer]]></category>
		<category><![CDATA[dependências]]></category>
		<category><![CDATA[pacotes]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1429</guid>

					<description><![CDATA[<p>O Composer é o gerenciador de dependências para PHP mais utilizado hoje em dia em todo o mundo. Ele permite que você defina bibliotecas externas usadas em seu projeto de forma simples. O próprio Composer se encarrega de baixar a biblioteca e carregá-la automaticamente em sua aplicação. É ridiculamente fácil usar o Composer! E ele faz [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/composer-php/">Composer: o gerenciador de dependências para PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" src="http://rberaldo.com.br/wp-content/uploads/2015/06/composer-post-img.jpg" alt="Composer: o gerenciador de dependências para PHP" width="560" height="292" class="aligncenter size-full wp-image-1433" srcset="http://rberaldo.com.br/wp-content/uploads/2015/06/composer-post-img.jpg 560w, http://rberaldo.com.br/wp-content/uploads/2015/06/composer-post-img-150x78.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/06/composer-post-img-300x156.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/06/composer-post-img-96x50.jpg 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>O <strong>Composer</strong> é o gerenciador de dependências para PHP mais utilizado hoje em dia em todo o mundo. Ele permite que você defina bibliotecas externas usadas em seu projeto de forma simples. O próprio Composer se encarrega de baixar a biblioteca e carregá-la automaticamente em sua aplicação.</p>
<p>É ridiculamente fácil usar o Composer! E ele faz todo o trabalho pesado de gerenciar as bibliotecas, baixar as versões corretas e carregá-las em seu projeto.</p>
<p>Ou seja, se você ainda não o usa, com certeza está perdendo MUITO tempo e produtividade!</p>
<p>Continue lendo este artigo, que vou explicar como instalar e utilizar essa maravilhosa ferramenta.</p>
<p><span id="more-1429"></span></p>
<h1>Instalação do Composer</h1>
<p>Há diferenças no processo de instalação em sistemas Windows e em Linux/Mac OS X. Vou abordá-las separadamente.</p>
<h3>Instalação em Linux e Mac OS X</h3>
<p>Em Linux e Mac, podemos usar as maravilhosas ferramentas de linha de comando, que facilitam muito o nosso dia-a-dia de programação.</p>
<blockquote><p>
Aliás, se você usa Linux ou Mac e não sabe como utilizar os comandos pra agilizar e automatizar suas tarefas, recomendo que dê uma olhada no meu curso <a href="http://shellparaprogramadores.com.br" target="_blank">Shell Script Para Programadores</a>.
</p></blockquote>
<p>Abra o terminal e rode este comando:</p>
<pre lang="bash">
curl -sS https://getcomposer.org/installer | php
</pre>
<p>O que o comando acima faz é baixar o instalador do Composer, usando curl, e executá-lo com o interpretador do PHP.</p>
<p>Caso você não tenha o curl instalado, o comando vai falhar. Você pode instalar o curl ou usar o comando abaixo, que também terá o mesmo resultado:</p>
<pre lang="bash">
php -r "readfile('https://getcomposer.org/installer');" | php
</pre>
<p>Se você rodar o comando <code>ls</code>, verá que o arquivo <code>composer.phar</code> agora está no diretório.</p>
<p>Você poderá executar o comando abaixo para testar a instalação:</p>
<pre lang="bash">
php composer.phar
</pre>
<p>Como você vai usar muito o Composer, em vários projetos, recomendo que, em vez de baixá-lo em todas aplicações, instale-o globalmente. Assim poderá executá-lo a partir de qualquer diretório, sem precisar baixá-lo de novo.</p>
<p>Para isso, vamos copiar o arquivo <code>composer.phar</code> para um diretório que esteja no <code>PATH</code> do nosso sistema. Pra facilitar, vamos renomeá-lo para <code>composer</code> apenas, sem extensão.</p>
<p>Vamos copiar o arquivo para o diretório <code>/usr/local/bin/</code>, com o comando <code>mv</code>:</p>
<pre lang="bash">
sudo mv composer.phar /usr/local/bin/composer
</pre>
<p>Note que <code>/usr/local/bin/</code> é um diretório protegido e você precisará de permissão de root para escrever nele. Por isso, executamos o comando usando <code>sudo</code>.</p>
<p>Pronto.</p>
<p>Agora o Composer está instalado globalmente. Basta digitar <code>composer</code> no terminal, em qualquer diretório e pode usá-lo onde quiser.</p>
<h3>Instalação em Windows</h3>
<p>A forma mais simples de instalar no Windows é usando o instalador. Também há a opção manual, se preferir.</p>
<p>Baixe o instalador <a href="https://getcomposer.org/Composer-Setup.exe" target="_blank">clicando aqui</a>. Depois execute-o e siga os passos.  O instalador vai colocar o Composer no <code>PATH</code> do seu Windows, assim você poderá executar o comando de qualquer diretório.</p>
<p>Note que, se você estiver com uma janela do terminal (prompt de comando) aberta, deverá fechá-la e abri-la novamente. Isso é necessário para que a alteração no <code>PATH</code> seja carregada.</p>
<p>Se preferir seguir a instalação manual, <a href="https://getcomposer.org/doc/00-intro.md#installation-windows" target="_blank">clique aqui</a> e execute os comandos descritos na documentação oficial.</p>
<p>[cta id=&#8217;1444&#8242;]</p>
<h2>Instalando Dependências</h2>
<p>Para instalar uma dependências, usaremos o comando <code>composer require &lt;vendor_name/project_name&gt;</code>. Um pacote é identificado por duas partes: <em>vendor_name</em> é o nome do responsável por ele e <em>project_name</em> é o nome do projeto propriamente dito.</p>
<p>Por exemplo, se quisermos instalar o Slim, vamos requerer o pacote <strong>slim/slim</strong>, desta forma:</p>
<pre lang="bash">
composer require slim/slim
</pre>
<p>NOTA: caso você não conheça, o Slim é um Micro-framework, muito útil para gerenciar rotas usando URLs Amigáveis, sem a necessidade de criar regras complexas no arquivo <code>.htaccess</code>. </p>
<p>Após alguns segundos, o Slim terá sido baixado automaticamente.</p>
<p>Os arquivos <code>composer.json</code> e <code>composer.lock</code> são criados automaticamente. A biblioteca Slim (e todas as demais dependências) serão armazenadas no diretório <code>vendor</code>.</p>
<p>O arquivo <code>composer.json</code> é o arquivo de configuração principal. É nele que são armazenadas as dependências, nome do projeto etc. </p>
<p>O <code>composer.lock</code> é um arquivo manipulado pelo próprio Composer, para gerenciar as versões, saber de onde baixar as bibliotecas etc. Você não precisa (e nem deve) mexer nele. </p>
<p>O diretório <code>vendor</code> é onde fica o <em>auto loader</em> e todas as dependências de seu projeto.</p>
<p>Você pode alterar o arquivo <code>composer.json</code> manualmente, se preferir. Mas é bem mais rápido e prático usar o comando <code>composer require</code> para isso. Ele altera o arquivo e já baixa a biblioteca automaticamente.</p>
<h2>Usando Dependências</h2>
<p>Uma vez que você tenha declarado e baixado uma dependência, você poderá usá-la em todo o seu projeto. Basta que o <em>autoloader</em> do Composer tenha sido carregado.</p>
<p>Se você possui um arquivo de <em>Bootstrapping</em>, esse é o local perfeito para incluir o <em>autoloader</em> do Composer. Você pode ler mais sobre Arquivos de Inicialização e Bootstrapping <a href="http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/" target="_blank">neste meu artigo</a>.</p>
<p>Vamos fazer um rápido teste usando o Slim, que já baixamos anteriormente.</p>
<p>No diretório atual (onde está o composer.json) crie um arquivo <code>index.php</code>. Nele, você precisa apenas incluir o arquivo <code>vendor/autoload.php</code> e você terá acesso a todas as dependências gerenciadas pelo Composer.</p>
<p>Vamos criar o <code>index.php</code> com este conteúdo:</p>
<pre lang="php">
<?php

require 'vendor/autoload.php';

$app = new \Slim\Slim();

$app->get('/', function()
{
    echo "Funcionou!";
});

$app->run();
</pre>
<p>Você pode iniciar o <a href="http://rberaldo.com.br/como-usar-o-servidor-nativo-do-php-5-4/" target="_blank">servidor nativo do PHP</a> e testar no navegador. Inicie o servidor na porta 8000:</p>
<pre lang="bash">
php -S localhost:8000
</pre>
<p>Depois basta acessar a URL <strong>http://localhost:8000</strong> em seu navegador e você verá a mensagem <em>Funcionou!</em>.</p>
<p>Pronto, viu como é simples? :)</p>
<h2>Atualizando Dependências</h2>
<p>Por ser um gerenciador, o Composer deve atualizar os pacotes baixados. Para isso, devemos usar o comando <code>composer update</code>. Esse comando verifica todas as dependências configuradas no arquivo <code>composer.json</code> e busca por atualizações. Dessa forma, elas estarão sempre atualizadas.</p>
<h2>Obtendo Ajuda</h2>
<p>Ao digitar apenas <code>composer</code>, sem parâmetros, será exibida a lista de comandos disponíveis. É possível atualizar a lista de repositórios (com <code>selfupdate</code>). Também é possível obter ajuda sobre um comando específico, usando a palavra <em>help</em> antes do comando, por exemplo <code>composer help require</code>.</p>
<h2>Aprenda Tudo Sobre o Composer</h2>
<p>Neste post mostrei apenas alguns recursos do Composer.</p>
<p>Se você quiser aprender todo o poder dessa ferramenta, conheça o meu curso <a href="http://ultimatecomposer.com.br" target="_blank">Ultimate Composer</a>.</p>
<p>No curso eu mostro outras configurações do Composer, a estrutura do arquivo de configuração <code>composer.json</code> e outros comandos disponíveis. </p>
<p>Também demonstro como usar o poderoso <em>autoloader</em> que ele fornece. Essa é um dos principais recursos do Composer e um dos melhores e mais práticos de usar!</p>
<p>Para fixar o conteúdo, vamos montar uma aplicação prática, usando o que aprendemos.</p>
<p>Aproveite a promoção por tempo limitado! O curso <a href="http://ultimatecomposer.com.br" target="_blank">Ultimate Composer</a> está custando apenas R$ 7,00! Mas é por pouco tempo!</p>
<p style="font-size: 1.2em;"><a href="http://ultimatecomposer.com.br" target="_blank">Clique aqui e conheça o Curso Ultimate Composer</a>!</p>
<p>&nbsp;</p>

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda TUDO Sobre o Composer!</h2>

<div class="uphp_cta_image" style="background: #666;">
	<a href="http://ultimatecomposer.com.br" target="_blank">
        <img src="http://ultimatecomposer.com.br/wp-content/uploads/2015/06/cover-332x450.png" alt="Curso Ultimate Composer" width="180">
	</a>
</div>

<div class="uphp_cta_text">
	<p>Gerencie as dependências da sua aplicação da forma mais eficiente possível!</p>
    
    <p>Com um único comando você baixa todas as dependências necessárias</p>

	<p>O mínimo de esforço com a máxima produtividade!</p>

	<div class="btn-download">
    	<a href="http://ultimatecomposer.com.br" target="_blank">
        	<img src="http://rberaldo.com.br/wp-content/uploads/2017/10/botao-saiba-mais-300x82.png" alt="Saiba Mais">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/composer-php/">Composer: o gerenciador de dependências para PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/composer-php/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1429</post-id>	</item>
		<item>
		<title>O Problema do N + 1: como identificá-lo, corrigi-lo e ganhar desempenho em suas aplicações</title>
		<link>http://rberaldo.com.br/o-problema-do-n-mais-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=o-problema-do-n-mais-1</link>
					<comments>http://rberaldo.com.br/o-problema-do-n-mais-1/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Tue, 09 Jun 2015 15:23:06 +0000</pubDate>
				<category><![CDATA[Banco de Dados]]></category>
		<category><![CDATA[Desempenho]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[desempenho]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[problema do n + 1]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1412</guid>

					<description><![CDATA[<p>Você se importa com o Desempenho de suas aplicações? Então é fundamental que você entenda o que é o Problema do N + 1 e saiba como identificá-lo e corrigi-lo. Essa é uma grande falha que muitos programadores iniciantes (e até intermediários) não conhecem, deixando as aplicações muito lentas e tendo uma grande perda de [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/o-problema-do-n-mais-1/">O Problema do N + 1: como identificá-lo, corrigi-lo e ganhar desempenho em suas aplicações</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter size-full wp-image-1413" src="http://rberaldo.com.br/wp-content/uploads/2015/06/problema-n_mais_um.jpg" alt="Problema do N + 1" width="560" height="292" srcset="http://rberaldo.com.br/wp-content/uploads/2015/06/problema-n_mais_um.jpg 560w, http://rberaldo.com.br/wp-content/uploads/2015/06/problema-n_mais_um-150x78.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/06/problema-n_mais_um-300x156.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/06/problema-n_mais_um-96x50.jpg 96w" sizes="(max-width: 560px) 100vw, 560px" /></p>
<p>Você se importa com o <strong>Desempenho</strong> de suas aplicações? Então é <strong>fundamental</strong> que você entenda o que é o <strong>Problema do N + 1</strong> e saiba como identificá-lo e corrigi-lo.</p>
<p>Essa é uma grande falha que muitos programadores iniciantes (e até intermediários) não conhecem, deixando as aplicações muito lentas e tendo uma grande perda de performance.</p>
<p>Continue lendo este artigo, que vou explicar em detalhes o que é o Problema do N + 1 e como solucioná-lo.</p>
<p><span id="more-1412"></span></p>
<h2>O Que é o Problema do N + 1</h2>
<p>Para explicar o que é esse problema, vamos considerar um banco de dados com duas tabelas: uma tabela de usuários e uma tabela de posts, como mostrado na imagem a seguir.</p>
<div id="attachment_1416" style="width: 610px" class="wp-caption aligncenter"><img aria-describedby="caption-attachment-1416" loading="lazy" class="wp-image-1416 size-full" src="http://rberaldo.com.br/wp-content/uploads/2015/06/modelagem-usuarios-posts1.png" alt="Modelagem para exemplificar o Problema do N + 1" width="600" height="177" srcset="http://rberaldo.com.br/wp-content/uploads/2015/06/modelagem-usuarios-posts1.png 600w, http://rberaldo.com.br/wp-content/uploads/2015/06/modelagem-usuarios-posts1-150x44.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/06/modelagem-usuarios-posts1-300x89.png 300w, http://rberaldo.com.br/wp-content/uploads/2015/06/modelagem-usuarios-posts1-169x50.png 169w" sizes="(max-width: 600px) 100vw, 600px" /><p id="caption-attachment-1416" class="wp-caption-text">Modelagem para exemplificar o Problema do N + 1</p></div>
<p>A tabela <code>Usuários</code> armazena os dados dos usuários, como nome, email, senha etc. A tabela de <code>posts</code>, além dos dados dos posts, como título e conteúdo, também possui o campo <code>user_id</code>, que referencia o ID do usuário que criou o post.</p>
<p>Até aí tudo bem. Modelagem bem simples.</p>
<p>Agora imagine que você precisa montar uma tela onde serão exibidos todos os usuários e os títulos de todos os posts de cada um deles.</p>
<p>O que muitos fariam é o seguinte:</p>
<ol>
<li>Selecionar todos os usuários, com a consulta a seguir:
<pre lang="sql">
SELECT id, nome FROM usuarios;
</pre>
</li>
<li>Em seguida, para cada usuário, seria feita a consulta a seguir:
<pre lang="sql">
SELECT titulo FROM posts WHERE user_id = id_do_usuario;
</pre>
</li>
</ol>
<p>Supondo que temos 100 usuários, serão executadas todas estas consultas:</p>
<pre lang="sql">
SELECT id, nome FROM usuarios;;
SELECT titulo FROM posts WHERE user_id = 1;
SELECT titulo FROM posts WHERE user_id = 2;
SELECT titulo FROM posts WHERE user_id = 3;
...
SELECT titulo FROM posts WHERE user_id = 100;
</pre>
<p>Veja que seriam feitas 101 consultas. E é aqui que você vai entender o motivo do <strong>N + 1</strong>.</p>
<p>Considerando <code>N</code> o número de usuários, nosso N vale 100. E N + 1 é 101, que foi o total de consultas realizadas.</p>
<p>Consultas a bancos de dados tomam tempo. Muito tempo. Por isso devemos usar sempre o mínimo de consultas.</p>
<p>E 101, definitivamente, não é o mínimo para chegarmos ao resultado esperado.</p>
<p>Esse número é BEM MENOR que 101&#8230; MUTO MENOR MESMO!</p>
<p>Você vai entender logo logo.</p>
<h2>Como Identificar o Problema do N + 1</h2>
<p>É simples identificar esse problema. Sempre que houver uma consulta dentro de um loop, é bem provável que ali esteja ocorrendo esse problema.</p>
<p>Vamos a um simples exemplo, usando PHP:</p>
<pre lang="php">
$PDO = new PDO( "dados de conexão aqui" );
$sql = "SELECT id, nome FROM usuarios";
$stmt = $PDO->prepare( $sql );
$result = $stmt->execute();
$users = $stmt->fetchAll( PDO::FETCH_ASSOC );

foreach ( $users as $user )
{
    $sql = "SELECT titulo FROM posts WHERE user_id = :user_id";
    $stmt = $PDO->prepare( $sql );
    $stmt->bindParam( ':user_id', $user['id'] );
    $result = $stmt->execute();
    $posts = $stmt->fetchAll( PDO::FETCH_ASSOC );
}
</pre>
<p><strong>NOTA</strong>: Caso você não conheça PDO, recomendo ler <a href="http://www.ultimatephp.com.br/como-usar-pdo-com-banco-de-dados-mysql/" target="_blank">este artigo</a>.</p>
<p>Veja que existe uma consulta dentro do loop. Ou seja, serão feitas N consultas, sendo N o total de elementos do array <code>$users</code> (100, no nosso caso).</p>
<h2>Como Resolver o Problema do N + 1</h2>
<p>Resolver esse problema é muito simples!</p>
<p>Vamos reduzir o números de consultas de <strong>N + 1</strong> para APENAS 2!</p>
<p><strong>Vamos usar SOMENTE DUAS CONSULTAS!</strong></p>
<p>A primeira vai continuar sendo a mesma de antes, responsável por buscar todos os usuários:</p>
<pre lang="sql">
SELECT id, nome FROM usuarios
</pre>
<p>Porém, a segunda vai usar os dados dessa consulta e trazer todos os posts de todos os usuários. Depois basta iterar sobre o array, dentro da programação.</p>
<p>A consulta usará a função <a href="http://www.w3schools.com/sql/sql_in.asp" target="_blank"><code>IN()</code></a> na cláusula <code>WHERE</code>, desta forma:</p>
<pre lang="sql">
SELECT titulo FROM posts WHERE user_id IN(1,2,3,4,5,...,100);
</pre>
<p>Vou modificar o código anterior e mostrar como resolver o Problema do N + 1 para o caso que analisamos.</p>
<pre lang="php">
$PDO = new PDO( "sua conexão aqui" );
$sql = "SELECT id, nome FROM usuarios";
$stmt = $PDO->prepare( $sql );
$result = $stmt->execute();
$users = $stmt->fetchAll( PDO::FETCH_ASSOC );

$userIDs = array_column( $users, 'id' );
$sqlIDs = implode( ',', $userIDs );
$sql = sprintf( "SELECT titulo FROM posts WHERE user_id IN(%s)", $sqlIDs );
$stmt = $PDO->prepare( $sql );
$result = $stmt->execute();
$posts = $stmt->fetchAll( PDO::FETCH_ASSOC );
</pre>
<p><em>Voilà!</em></p>
<p>Note que, até a criação da variável <code>$users</code>, nada mudou. Depois disso é que apareceram as novidades. Vamos analisá-las com mais calma.</p>
<p>Criei a variável <code>$userIDs</code>, que é um array com todos os valores do campo <code>id</code> que estavam no array <code>$users</code>. Isso ficou fácil usando a função <a href="http://php.net/array_column" target="_blank"><code>array_column</code></a>.</p>
<p>Em seguida criei a variável <code>$sqlIDs</code>, usando a função <a href="http://php.net/implode" target="_blank"><code>implode</code></a>. Essa variável é uma string com todos os IDs separados por vírgula, de forma que possa ser usada no parâmetro da função <code>IN</code> da SQL.</p>
<p>Depois criei a variável <code>$sql</code>, que vai buscar todos os posts com uma única consulta.</p>
<h2>Analisando o Ganho de Desempenho</h2>
<p>Vamos fazer um simples teste de desempenho, para comparar os dois códigos que vimos anteriormente.</p>
<p>A análise é simples: pegar a hora de início do script, a hora final e subtrair. Para isso, usarei a função <a href="http://php.net/microtime" target="_blank"><code>microtime</code></a>, para pegar o tempo atual em micro-segundos, e a função <a href="http://php.net/number_format" target="_blank"><code>number_format</code></a>, para formatar o tempo de maneira a ficar mais facilmente legível.</p>
<p>A ideia geral, em termos de código é a seguinte:</p>
<pre lang="php">
$inicio = microtime( true );

// código cujo desempenho queremos testar

$fim = microtime( true );
$diff = number_format( $fim - $inicio, 15, ',', '.' );

echo "Tempo total: " . $diff . PHP_EOL;
</pre>
<p>Para testar, criei 100 registros na tabela de usuários, com valores aleatórios. Criei 1000 registros, também aleatórios, na tabela de posts.</p>
<p>Vamos aos resultados&#8230;</p>
<p>O script contendo o Problema do N + 1 foi executado em <strong>0,0198240280</strong> segundos.</p>
<p>Já o script sem o problema foi executado em <strong>0,0015311241</strong> segundos. Ou seja, aproximadamente 13 vezes mais rápido.</p>
<p><strong>13 VEZES MAIS RÁPIDO!</strong></p>
<p>E olha que o exemplo tinha poucos dados. Um sistema real geralmente tem muito mais que 100 usuários e mais de 1000 registros relacionados a eles.</p>
<p><a name="in_vs_join"></a></p>
<h2>Por que não usei JOIN em vez do IN</h2>
<p>É possível resolver esse problema com apenas uma consulta, usando <code>JOIN</code> em vez de <code>IN</code>, desta forma:</p>
<pre lang="sql">
SELECT u.id, u.nome, p.titulo FROM usuarios u INNER JOIN posts p ON p.user_id = u.id
</pre>
<p>Mas isso não significa que será mais <strong>eficiente</strong>.</p>
<p>O foco aqui é <strong>Desempenho</strong>, não apenas menos consultas.</p>
<p>Se cada usuário tivesse apenas um post, poderia ser mais eficiente usar JOIN. Mas se, por exemplo, cada usuário tiver, em média, 100 posts, haverá milhares de dados repetidos trafegando entre o banco de dados e sua aplicação. E isso tomará tempo e memória.</p>
<p>Já que estamos fazendo testes práticos, vamos comparar os tempos de execução de dois scripts, um usando o IN (que é o mesmo código que mostrei anteriormente) e outro usando JOIN.</p>
<p>O código usando JOIN é este:</p>
<pre lang="php">
$PDO = new PDO( "conexão aqui" );
$sql = "SELECT u.id, u.nome, p.titulo FROM usuarios u INNER JOIN posts p ON p.user_id = u.id";
$stmt = $PDO->prepare( $sql );
$result = $stmt->execute();
$posts = $stmt->fetchAll( PDO::FETCH_ASSOC );
</pre>
<p>Vou mostrar os resultados para um conjunto de 100 usuários e 1000 posts. Em seguida, vou inserir mais 4000 posts, resultando em 100 usuários e 5000 posts.</p>
<p>Alguns resultados de execução para 100 usuários e 1000 posts:</p>
<pre lang="plain">
$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,002864837646484
  Tempo total com IN: 0,002188920974731

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,002944946289063
  Tempo total com IN: 0,001436948776245

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,003201961517334
  Tempo total com IN: 0,001392841339111

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,002935886383057
  Tempo total com IN: 0,001415014266968

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,002933025360107
  Tempo total com IN: 0,001442193984985
</pre>
<p>Agora vamos a alguns resultados usando 100 usuários e 5000 posts:</p>
<pre lang="plain">
$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,011201143264771
  Tempo total com IN: 0,002874851226807

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,010854005813599
  Tempo total com IN: 0,002540111541748

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,010561943054199
  Tempo total com IN: 0,002592086791992

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,010941982269287
  Tempo total com IN: 0,002531051635742

$ php select_join.php && php select_in.php
Tempo total com JOIN: 0,010515928268433
  Tempo total com IN: 0,002762794494629
</pre>
<p>Fiz cinco execuções de cada script para cada conjunto de dados. </p>
<p>De todos os 10 testes, 9 resultaram em desempenho superior na versão usando IN. O uso do JOIN ficou superior apenas na primeira execução com 1000 posts.</p>
<p>Não estou falando para abandonar o JOIN e usar só o IN. Tudo depende da sua modelagem e da quantidade de dados. Para poucos dados ou relação 1 Para 1, o JOIN será melhor. Mas em relação 1 Para Muitos, o IN tende a ter melhor desempenho.</p>
<h2>Conclusão</h2>
<p>Melhorias de desempenho são sempre muito bem-vindas. Qualquer ajuste que dê 5% de ganho já é válido. </p>
<p>E considerando que aqui tivemos 13 vezes mais (ou seja, 1300%), você <strong>definitivamente</strong> precisa saber identificar e resolver o Problema do N + 1 nas aplicações que você desenvolve ou dá manutenção.</p>
<p>É uma medida simples e que dá resultados fantásticos!</p>
<h2>Otimizações Avançadas</h2>
<p>Há inúmeras outras formas mais avançadas de otimizar seu banco de dados.</p>
<p>Para conhecer essas técnicas, recomendo o curso <a href="http://rberaldo.com.br/curso-tuning-mysql" target="_blank"><em>Tuning MySQL</em></a> (curso em português), especialmente voltado para o MySQL, um dos mais usados do Mercado.</p>
<p>Você vai aprender passo-a-passo como instalar e configurar o MySQL da forma mais otimizada para a sua aplicação, conhecendo cada um dos arquivos de configuração e suas diretivas. Também vai descobrir como realizar análises de desempenho e testes de stress, para comparar o desempenho padrão e o desempenho obtido após o <em>tuning</em>.</p>
<p><a href="http://rberaldo.com.br/curso-tuning-mysql" target="_blank">Clique Aqui e conheço o Curso <em>Tuning MySQL</em></a></p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/o-problema-do-n-mais-1/">O Problema do N + 1: como identificá-lo, corrigi-lo e ganhar desempenho em suas aplicações</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/o-problema-do-n-mais-1/feed/</wfw:commentRss>
			<slash:comments>23</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1412</post-id>	</item>
		<item>
		<title>Honeypot: Captcha Acessível Sem Utilização de Imagens</title>
		<link>http://rberaldo.com.br/captcha-acessivel-sem-utilizacao-imagens/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=captcha-acessivel-sem-utilizacao-imagens</link>
					<comments>http://rberaldo.com.br/captcha-acessivel-sem-utilizacao-imagens/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Sun, 19 Apr 2015 18:53:21 +0000</pubDate>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[acessibilidade]]></category>
		<category><![CDATA[acessível]]></category>
		<category><![CDATA[captcha]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1365</guid>

					<description><![CDATA[<p>Neste meu antigo post eu mostrei como usar algumas técnicas de Captcha envolvendo imagens. O grande problema disso está no quesito acessibilidade. Leitores de tela não identificam as imagens, dificultando a navegação para deficientes visuais. Outro problema é o incômodo para o usuário. Ele precisa identificar caracteres distorcidos em uma imagem, para provar que não [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/captcha-acessivel-sem-utilizacao-imagens/">Honeypot: Captcha Acessível Sem Utilização de Imagens</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1366 size-full" src="http://rberaldo.com.br/wp-content/uploads/2015/04/no-image-captcha.jpg" alt="Captcha Acessível Sem Utilização de Imagens" width="380" height="415" srcset="http://rberaldo.com.br/wp-content/uploads/2015/04/no-image-captcha.jpg 380w, http://rberaldo.com.br/wp-content/uploads/2015/04/no-image-captcha-137x150.jpg 137w, http://rberaldo.com.br/wp-content/uploads/2015/04/no-image-captcha-275x300.jpg 275w, http://rberaldo.com.br/wp-content/uploads/2015/04/no-image-captcha-46x50.jpg 46w" sizes="(max-width: 380px) 100vw, 380px" /></p>
<p><a title="Técnicas de CAPTCHA" href="http://rberaldo.com.br/tecnicas-de-captcha/">Neste meu antigo post</a> eu mostrei como usar algumas técnicas de Captcha envolvendo imagens. O grande problema disso está no quesito acessibilidade. Leitores de tela não identificam as imagens, dificultando a navegação para deficientes visuais.</p>
<p>Outro problema é o incômodo para o usuário. Ele precisa identificar caracteres distorcidos em uma imagem, para provar que não é um robô. Isso é muito chato.</p>
<p>Há poucos meses, <a href="http://googleonlinesecurity.blogspot.com.br/2014/12/are-you-robot-introducing-no-captcha.html" target="_blank">o Google anunciou uma nova forma de verificação anti-bot</a>, para substituir o reCaptcha, propriedade da empresa. A abordagem é bem simplista, mas ainda envolve uma ação do usuário.</p>
<p>Neste post vou mostrar a técnica <em><strong>Honeypot</strong></em>, que eu uso há alguns anos e que tem dado resultados de praticamente 100% contra spam. E o melhor: não requer ação alguma do dos usuários.</p>
<p><span id="more-1365"></span></p>
<h2>Como Funciona Esse Captcha <em>Honeypot</em></h2>
<p>O &#8220;segredo&#8221; são campos ocultos. Só isso.</p>
<p>Explicando melhor: eu crio dois campos ocultos. Um deles é um campo input do tipo <em>hidden</em> (oculto). O outro é um input <em>text</em> (texto) oculto via CSS. Ambos possuem o valor vazio.</p>
<p>Ou seja, ambos os campos são invisíveis a usuários comuns. Consequentemente, não serão preenchidos por eles. Caso algum desses campos possua um valor não vazio, significa que o formulário foi enviado por um robô.</p>
<h2>Exemplo do Captcha <em>Honeypot</em> em Ação</h2>
<p>Para exemplificar, vamos criar este formulário:</p>
<pre lang="html4strict">
<form action="seu_script.php" method="post">
  <input name="nome" type="text" placeholder="Nome"> 
  <br>
  <input name="cidade" type="text" placeholder="Cidade"> 
  <br>
  <input name="check_1" type="hidden" value="">
  <input style="position: absolute; width: 1px; top: -5000px; left: -5000px;" name="check_2" type="text">
  <br>
  <input type="submit" value="Enviar">
</form>
</pre>
<p>Na página que recebe o formulário (aqui chamei de <code>seu_script.php</code>), faremos o seguinte:</p>
<pre lang="php">
<?php 
$nome = isset( $_POST['nome'] ) ? $_POST['nome'] : null; 
$cidade = isset( $_POST['cidade'] ) ? $_POST['cidade'] : null;  
$check_1 = isset( $_POST['check_1'] ) ? $_POST['check_1'] : null;  
$check_2 = isset( $_POST['check_2'] ) ? $_POST['check_2'] : null;  

if ( ! empty( $check_1 ) || ! empty( $check_2 ) ) 
{
     echo "Você é um robô!";
     exit;  
} 

printf( "Nome: %s | Cidade: %s", $nome, $cidade );
?>
</pre>
<p>O código HTML tem dois campos ocultos. Ambos com valor vazio. No script PHP, verificamos se ambos são vazios. Se algum deles tiver valor diferente de vazio, exibimos uma mensagem de alerta e interrompemos o script.</p>
<p>Pronto. Bem simples. :)</p>
<h2>Conclusão</h2>
<p>Para mim, essa abordagem tem eficácia de praticamente 100%. Pouquíssimos robôs passaram por essa verificação.</p>
<p>A melhor coisa dessa técnica é o não envolvimento do usuário. Ele não precisa identificar caracteres em imagens nem clicar em checkbox dizendo &#8220;Não sou um robô&#8221;.</p>
<p>A lógica aqui é assumir primeiro que o visitante não é um robô. Ao contrário das outras, que primeiro assumem que é um robô e, para provar o oposto, o usuário é forçado a tomar alguma ação.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/captcha-acessivel-sem-utilizacao-imagens/">Honeypot: Captcha Acessível Sem Utilização de Imagens</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/captcha-acessivel-sem-utilizacao-imagens/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1365</post-id>	</item>
		<item>
		<title>Como Gerar Logs de Execução com PHP</title>
		<link>http://rberaldo.com.br/como-gerar-logs-execucao-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=como-gerar-logs-execucao-php</link>
					<comments>http://rberaldo.com.br/como-gerar-logs-execucao-php/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Fri, 03 Apr 2015 23:30:11 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Segurança]]></category>
		<category><![CDATA[erros]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[segurança]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1310</guid>

					<description><![CDATA[<p>Logs de execução são muito úteis para &#8220;catalogar&#8221; o ciclo de execução de um programa. Cada ação executada pelo software é registrada em um arquivo, juntamente com a data e a hora do ocorrido. Muitos programadores enchem a tela de echo e var_dump, para descobrir o que está ocorrendo no código. Isso não é totalmente [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/como-gerar-logs-execucao-php/">Como Gerar Logs de Execução com PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" src="http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-300x157.png" alt="Como Gerar Logs de Execução com PHP" width="300" height="157" class="aligncenter size-medium wp-image-850" srcset="http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-300x157.png 300w, http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-150x78.png 150w, http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-95x50.png 95w, http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_.png 800w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>Logs de execução são muito úteis para &#8220;catalogar&#8221; o ciclo de execução de um programa. Cada ação executada pelo <em>software</em> é registrada em um arquivo, juntamente com a data e a hora do ocorrido.</p>
<p>Muitos programadores enchem a tela de <code>echo</code> e <code>var_dump</code>, para descobrir o que está ocorrendo no código. Isso não é totalmente errado, mas há alternativas melhores. Aliás, já vi gente esquecer de tirar <code>var_dump</code> antes de mandar o sistema pro ar. Resultado: todo mundo vendo o <em>debug</em> ao acessar o site&#8230; </p>
<p>Neste artigo vou mostrar como criar um simples sistema de logs usando PHP.</p>
<p><span id="more-1310"></span></p>
<h2>Como Um Arquivo de Logs Deve Ser</h2>
<p>Um simples exemplo de um registro em um arquivo de log é o seguinte:</p>
<pre lang="plain">
[2015-03-31 00:00:00] INFO: Executando ação X...
</pre>
<p>Bem simples. Nada especial.</p>
<p>O arquivo nada mais é do que um conjunto de registros, um por linha, que indicam a data e a hora em que um determinado evento ocorreu.</p>
<p>No exemplo acima, incluí o nível do log, que é representado pela palavra <strong>INFO</strong>. Nesse caso, é um log de <strong>Informação</strong>. Poderíamos ter outros níveis, como <strong>Avisos</strong> (<em>Warning</em>) e erros (<em>Error</em>).</p>
<h2>Função Para Gerar Logs</h2>
<p>Vou mostrar uma simples função para criação de logs.</p>
<p>Vamos considerar os três tipos (aqui chamo de <strong>níveis</strong>) de logs que citei antes aqui no artigo.</p>
<p>Vou chamar a função de <code>logMsg</code>. Ela aceita três parâmetros, mas apenas o primeiro é obrigatório.</p>
<p>O primeiro parâmetro é a mensagem do log. O segundo é o nível do log (pode ser <code>info</code>, que é o valor padrão, <code>warning</code> ou <code>error</code>). O terceiro parâmetro é o nome do arquivo onde o log será escrito. Por padrão, será escrito no arquivo <code>main.log</code>.</p>
<p>Vamos ao código, com os deviso comentários.</p>
<pre lang="php">
function logMsg( $msg, $level = 'info', $file = 'main.log' )
{
    // variável que vai armazenar o nível do log (INFO, WARNING ou ERROR)
    $levelStr = '';

    // verifica o nível do log
    switch ( $level )
    {
        case 'info':
            // nível de informação
            $levelStr = 'INFO';
            break;

        case 'warning':
            // nível de aviso
            $levelStr = 'WARNING';
            break;

        case 'error':
            // nível de erro
            $levelStr = 'ERROR';
            break;
    }

    // data atual
    $date = date( 'Y-m-d H:i:s' );

    // formata a mensagem do log
    // 1o: data atual
    // 2o: nível da mensagem (INFO, WARNING ou ERROR)
    // 3o: a mensagem propriamente dita
    // 4o: uma quebra de linha
    $msg = sprintf( "[%s] [%s]: %s%s", $date, $levelStr, $msg, PHP_EOL );

    // escreve o log no arquivo
    // é necessário usar FILE_APPEND para que a mensagem seja escrita no final do arquivo, preservando o conteúdo antigo do arquivo
    file_put_contents( $file, $msg, FILE_APPEND );
}
</pre>
<h2>Como Usar A Função de Geração de Logs</h2>
<p>Para usar a função <code>logMsg</code> que criamos, basta chamá-la com, pelo menos, o primeiro parâmetro.</p>
<p>Vamos a alguns exemplos.</p>
<h3>Geração de Log de Informação</h3>
<p>Para gerar um simples log de informação, use o seguinte exemplo.</p>
<pre lang="php">
logMsg( "Executando a tarefa X..." );
</pre>
<p>Isso vai gerar a seguinte linha no arquivo de log</p>
<pre lang="plain">
[2015-04-03 22:07:03] [INFO]: Executando a tarefa X...
</pre>
<h3>Geração de Log de Aviso</h3>
<p>Para gerar um log de aviso, use o seguinte exemplo.</p>
<pre lang="php">
logMsg( "Isto é um aviso.... a operação X pode falhar...", 'warning' );
</pre>
<p>Isso vai gerar a seguinte linha no arquivo de log</p>
<pre lang="plain">
[2015-04-03 22:0703] [WARNING]: Isto é um aviso.... a operação X pode falhar...
</pre>
<h3>Geração de Log de Erro</h3>
<p>Para gerar um log de erro, use o seguinte exemplo.</p>
<pre lang="php">
logMsg( "Isto é um erro. A operação X falhou", 'error' );
</pre>
<p>Isso vai gerar a seguinte linha no arquivo de log</p>
<pre lang="plain">
[2015-04-03 22:0703] [ERROR]: Isto é um erro. A operação X falhou
</pre>
<h2>Por Que Não Usei a Função <code>error_log</code> do PHP</h2>
<p>O PHP possui a função <a href="http://php.net/manual/pt_BR/function.error-log.php" target="_blank"><code>error_log</code></a>. Você é livre para usá-la, se desejar.</p>
<p>Eu preferi não usá-la pois ela não permite usar as configurações a mais que acho úteis, como o nível de log. Ela é mais focada em erros, como o próprio nome da mensagem sugere.</p>
<h2>Cuidado Com a Quantidade de Logs</h2>
<p>Logs são muito úteis, claro. Mas existe um custo para o servidor.</p>
<p>Cada escrita no arquivo toma tempo da CPU e deixa sua aplicação um pouco mais lenta. É pouco perceptível quando há poucos logs. </p>
<p>Porém, se você configurar muitas gerações de logs, verá uma queda no desempenho. Principalmente se seu sistema receber muitos acessos simultâneos. Afinal, escrita em disco é uma das tarefas mais custosas para a CPU.</p>
<p>Por isso, use os logs com cautela. Gere logs apenas quando realmente necessário. Não crie logs inúteis. E, se gerar logs apenas para <em>debug</em> durante o desenvolvimento, lembre-se de removê-los antes de colocar a aplicação em produção.</p>
<h2>Padrão PSR-3 de Logs</h2>
<p>O grupo <a href="http://www.php-fig.org" target="_blank">PHP-Fig</a> criou, dentre outras recomendações, o <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md" target="_blank">PSR-3</a>, que é uma recomendação de padronização para bibliotecas de geração de logs.</p>
<p>Se você já tem conhecimentos sobre Orientação a Objetos, recomendo <a href="https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md" target="_blank"> analisar o PSR-3</a> e tentar aplicar em seus projetos. Se ainda não conhecer OOP, vá com calma. Use a função que mostrei nesse post e, depois, quando já tiver domínio de OOP, aplique os conceitos do PSR-3.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/como-gerar-logs-execucao-php/">Como Gerar Logs de Execução com PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/como-gerar-logs-execucao-php/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1310</post-id>	</item>
		<item>
		<title>As Diferentes Formas de Execução do PHP</title>
		<link>http://rberaldo.com.br/diferentes-formas-execucao-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=diferentes-formas-execucao-php</link>
					<comments>http://rberaldo.com.br/diferentes-formas-execucao-php/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Thu, 12 Mar 2015 22:11:28 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[execução]]></category>
		<category><![CDATA[interativo]]></category>
		<category><![CDATA[servidor]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[web]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1230</guid>

					<description><![CDATA[<p>O PHP é amplamente conhecido como uma linguagem para desenvolvimento de aplicações Web. Porém, nem só de Web vive o PHP. Existem outras formas de execução do PHP. É possível executá-lo em linha de comando também. Há, inclusive, uma forma de executar o PHP em um terminal interativo. Execução do PHP em Servidor Web Essa é [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/diferentes-formas-execucao-php/">As Diferentes Formas de Execução do PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1231 size-full" src="http://rberaldo.com.br/wp-content/uploads/2015/03/terminal-php-cli.png" alt="As Diferentes Formas de Execução do PHP" width="256" height="256" srcset="http://rberaldo.com.br/wp-content/uploads/2015/03/terminal-php-cli.png 256w, http://rberaldo.com.br/wp-content/uploads/2015/03/terminal-php-cli-150x150.png 150w, http://rberaldo.com.br/wp-content/uploads/2015/03/terminal-php-cli-50x50.png 50w, http://rberaldo.com.br/wp-content/uploads/2015/03/terminal-php-cli-200x200.png 200w" sizes="(max-width: 256px) 100vw, 256px" /></p>
<p>O PHP é amplamente conhecido como uma linguagem para desenvolvimento de aplicações Web. Porém, nem só de Web vive o PHP. Existem outras formas de execução do PHP. É possível executá-lo em linha de comando também. Há, inclusive, uma forma de executar o PHP em um terminal interativo.</p>
<p><span id="more-1230"></span></p>
<h2>Execução do PHP em Servidor Web</h2>
<p>Essa é a forma mais conhecida. É possível usar servidores como Apache, Nginx, IIS e outros, mas poucos conhecem o <a title="Como usar o servidor nativo do PHP 5.4" href="http://rberaldo.com.br/como-usar-o-servidor-nativo-do-php-5-4/">servidor interno do PHP</a>, disponível a partir da versão 5.4</p>
<p>Crie um arquivo <code>index.php</code>, com este conteúdo:</p>
<pre lang="php">
<?php
echo "Usando o servidor interno do PHP";
</pre>
<p>Salva o arquivo. Abra o terminal (aliás, ele já deveria estar aberto :P) e entre no diretório onde salvou o <code>index.php</code>. Execute este comando:</p>
<pre lang="bash">php -S localhost:8000
</pre>
<p>Esse comando vai iniciar o servidor interno do PHP na porta 8000. É possível alterar a porta, se você já tiver outra aplicação rodando nessa porta ou simplesmente não goste do número 8000. :P</p>
<p>Será exibida esta saída:</p>
<pre lang="plain">PHP 5.6.6 Development Server started at Thu Mar 12 21:44:26 2015
Listening on http://localhost:8000
Document root is /private/tmp
Press Ctrl-C to quit.
</pre>
<p>Pronto. Seu servidor está ativo. Acess a URL <strong> http://localhost:8000</strong> e lá estará a mensagem "Usando o servidor interno do PHP". Para parar o servidor, digite "CTRL+C".</p>
<p>Não entrarei em detalhes sobre as formas de execução do PHP em outros servidores Web. Há diversos artigos específicos sobre isso. Só pesquisar no Google.</p>
<h2>Execução do PHP em Linha de Comando</h2>
<p>Ainda não fechou o terminal, né? Então, ainda no diretório onde está seu script <code>index.php</code>, execute este comando:</p>
<pre lang="bash">php index.php 
</pre>
<p>A mensagem "Usando o servidor interno do PHP" será exibida no terminal. Porém não há quebra de linha no final dela. Vamos editar o arquivo <code>index.php</code>, deixando-o assim:</p>
<pre lang="php">
<?php
echo "Usando o PHP em linha de comando" . PHP_EOL;
</pre>
<p>A constante <code>PHP_EOL</code> corresponde ao "fim de linha" (<em><strong>E</strong>nd <strong>O</strong>f <strong>L</strong>ine</em>). Ela permite criar scripts portáveis, já que a quebra de linha em Linux e Mac OS X (e outros derivados de Unix) é "\n" e no Windows é "\r\n".</p>
<p>Ao executar novamente o comando <code>php index.php</code>, o seguinte resultado aparecerá no terminal:</p>
<pre lang="php">Usando o PHP em linha de comando
</pre>
<h2>Execução do PHP no Terminal Interativo</h2>
<p>O PHP tem um terminal interativo. Ou seja, é um terminal onde, a cada comando digitado, ele é imediatamente executado. Por exemplo, ao executar um <code>echo</code>, a mensagem é exibida na tela.</p>
<p>Para iniciar o terminal interativo, digite o seguinte comando no terminal:</p>
<pre lang="bash">php -a
</pre>
<p>Pronto. Você está no terminal interativo. Pode digitar qualquer comando PHP, que ele será executado. O ponto-e-vírgula continua sendo obrigatório aqui. Lembre-se dele!</p>
<p>Vamos a alguns exemplos:</p>
<pre lang="bash">$ php -a
Interactive shell

php > echo "Hello World";
Hello World
php > $x = 2;
php > echo pow( $x, 10 );
1024
php > echo "sem ponto-e-virgula"
php > ;
sem ponto-e-virgula
</pre>
<p>Veja que, se você esquecer o ponto-e-vírgula, poderá colocá-lo na linha seguinte, sem gerar qualquer erro.</p>
<p>Esse terminal interativo é útil quando você quer testar alguma função, sem a necessidade de criar um script somente para isso.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/diferentes-formas-execucao-php/">As Diferentes Formas de Execução do PHP</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/diferentes-formas-execucao-php/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1230</post-id>	</item>
		<item>
		<title>grep: como buscar em arquivos no Linux</title>
		<link>http://rberaldo.com.br/grep-como-buscar-em-arquivos-linux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=grep-como-buscar-em-arquivos-linux</link>
					<comments>http://rberaldo.com.br/grep-como-buscar-em-arquivos-linux/#respond</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Wed, 14 Jan 2015 10:32:05 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Shell Script (Bash)]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[comando]]></category>
		<category><![CDATA[egrep]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[Shell]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1070</guid>

					<description><![CDATA[<p>O comando grep é utilizado para buscar strings e padrões (usando Expressões Regulares) dentro de arquivos. O nome do comando significa global regular expression print, ou seja, ele imprime trechos de arquivos que correspondam a uma determinada expressão regular. Você pode usar apenas strings para realizar as buscas. Porém, o uso de Expressões Regulares abre um grande leque de [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/grep-como-buscar-em-arquivos-linux/">grep: como buscar em arquivos no Linux</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1073 size-medium" src="http://rberaldo.com.br/wp-content/uploads/2015/01/grep-300x113.jpg" alt="grep: como buscar em arquivos no Linux" width="300" height="113" srcset="http://rberaldo.com.br/wp-content/uploads/2015/01/grep-300x113.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/01/grep-150x56.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/01/grep-133x50.jpg 133w, http://rberaldo.com.br/wp-content/uploads/2015/01/grep-624x235.jpg 624w, http://rberaldo.com.br/wp-content/uploads/2015/01/grep.jpg 800w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>O comando grep é utilizado para buscar strings e padrões (usando Expressões Regulares) dentro de arquivos. O nome do comando significa <b>g</b>lobal <b>r</b>egular <b>e</b>xpression <b>p</b>rint, ou seja, ele imprime trechos de arquivos que correspondam a uma determinada expressão regular.</p>
<p>Você pode usar apenas strings para realizar as buscas. Porém, o uso de Expressões Regulares abre um grande leque de opções para buscas avançadas. Se você não conhece Expressões Regulares, sugiro que leia <a href="http://aurelio.net/regex/guia/" target="_blank">Expressões Regulares &#8211; Guia de Consulta Rápida</a>, de Aurelio Marinho Jargas, disponível gratuitamente na Internet pelo próprio autor.</p>
<p><span id="more-1070"></span></p>
<p><strong>Nota</strong>: Este artigo é um a versão reduzida do artigo bônus do curso <a title="Shell Script Para Programadores" href="http://shellparaprogramadores.com.br"><strong>Shell Script Para Programadores</strong></a>. Para conhecer melhor o curso e fazer sua matrícula, <a title="Shell Script Para Programadores" href="http://shellparaprogramadores.com.br"><strong>clique aqui</strong></a>.</p>
<p>&nbsp;</p>
<p>A sintaxe do comando grep é a seguinte:</p>
<pre lang="bash">$ grep [opcoes] arquivo
</pre>
<p>O comando <code>grep</code> funciona da seguinte forma: ele lê um arquivo linha a linha. Se a linha lida corresponder ao padrão (Expressão Regular) usada na filtragem, a linha é exibida na saída padrão. O comportamento da exibição pode ser modificado com as opções que veremos adiante, como exibir apenas o nome do arquivo, incluir número de linha, exibir só o texto que coincidiu com o padrão etc.</p>
<p>Em vez de abordar a fundo a parte teórica, vou ficar em exemplos práticos. Antes disso, precisamos ver as principais opções do comendo <code>grep</code>.</p>
<h2>Principais Opções do Comando <code>grep</code></h2>
<p>Existem inúmeras opções que podem ser utilizadas com o comando grep. Vou falar apenas das mais comuns e principais. As opções mais usadas são:</p>
<ul>
<li><code>-A NUM, --after-context=NUM</code>: exibe <code>NUM</code> linhas após a linha onde o padrão foi encontrado;</li>
<li><code>-B NUM, --before-context=NUM</code>: exibe <code>NUM</code> linhas antes da linha onde o padrão foi encontrado;</li>
<li><code>-C NUM, -NUM, --context=NUM</code> exibe <code>NUM</code> linhas antes e <code>NUM</code> linhas depois da linha onde o padrão foi encontrado;</li>
<li><code>-c, --count</code>: conta o total de linhas que coincidiram com o padrão;</li>
<li><code>--color, --colour</code>: ativa a exibição de cores, destacando o trecho que coincide com o padrão;</li>
<li><code>-E, --extended-regexp</code>: Interpreta as Expressões Regulares usando o modo POSIX (equivale a usar o comando <code>egrep</code> em vez do <code>grep</code>;</li>
<li><code>-i, --ignore-case</code>: Modo <em>case-<strong>i</strong>nsensitive</em>. Não diferencia maiúsculas de minúsculas;</li>
<li><code>-l, --files-with-matches</code>: em vez de exibir a saída normal, exibe apenas os nomes dos arquivos que coincidem com o padrão;</li>
<li><code>-n, --line-number</code>: exibe o número da linha onde o padrão foi encontrado;</li>
<li><code>-o, --only-matching</code>: exibe apenas o trecho da linha que coincide com o padrão;</li>
<li><code>-R, -r, --recursive</code>: realiza busca recursiva;</li>
<li><code>-x, --line-regexp</code>: filtra por linhas que coincidam exatamente com o padrão;</li>
<li><code>-v, --invert-match</code>: Inverte o modo de assimilação. A busca é feita por linhas que <strong>não</strong> coincidam com o padrão;</li>
</ul>
<p>Se você está habituado(a) a usar o padrão POSIX de Expressões Regulares (com os quantificadores <code>+</code>, <code>{NUM}</code> etc), é preferível usar o comando <code>egrep</code> em vez do <code>grep</code>. Isso poupa você de ter que usar a opção <code>-E</code> sempre que for usar esse padrão de Expressão Regular.</p>
<h2>Arquivo Para os Exemplos</h2>
<p>Para ilustrar os exemplos, será útil utilizar um arquivo de texto. Usarei um arquivo de dicionário, que possui milhares de palavras e nomes da Língua Portuguesa. Esse arquivo pode ser baixado <a href="http://rberaldo.com.br/wp-content/uploads/2015/01/wordlist-preao-20150102.txt.zip">aqui</a> (está compactado em ZIP).</p>
<h2>Exemplos de Uso</h2>
<p>Como eu citei antes, se você estiver habituado(a) a usar Expressões Regulares (ERs) do padrão POSIX, será melhor usar <code>egrep</code> em vez de <code>grep</code>. Como eu sou uma dessas pessoas, vou usar <code>egrep</code> em todos os exemplos, mesmo quando não utilizar expressões regulares. É uma simples questão de hábito pessoal. :)</p>
<h3>Filtrando linhas por uma string</h3>
<pre lang="bash">$ egrep 'programador' wordlist-preao-20150102.txt
desprogramador
desprogramadora
desprogramadoras
desprogramadores
programador
programadora
programadoras
programadores
reprogramador
reprogramadora
reprogramadoras
reprogramadores
</pre>
<p>O comando exibe todas as linhas que contenham a palavra &#8220;programador&#8221;.</p>
<h3>Contando as ocorrências de um padrão</h3>
<p>Para exibir o total de ocorrências de um padrão em vez da saída padrão do grep, usamos a opção <code>-c</code>:</p>
<pre lang="bash">$ egrep -c 'programador' wordlist-preao-20150102.txt
12
</pre>
<h3>Filtrando por linha exata</h3>
<p>Se quisermos apenas a linha onde há a palavra &#8220;programador&#8221;, exatamente, usamos a opção <b><code>-x</code></b>:</p>
<pre lang="bash">$ egrep -x 'programador' wordlist-preao-20150102.txt
programador
</pre>
<p>Se quisermos buscar por &#8220;programador&#8221; ou &#8220;programadora&#8221;, basta utilizarmos o básico sobre ERs:</p>
<pre lang="bash">$ egrep -x 'programadora?' wordlist-preao-20150102.txt
programador
programadora
</pre>
<h3>Exibindo o número da linha</h3>
<p>Para exibir o número da linha, usamos a opção <b><code>-n</code></b>:</p>
<pre lang="bash">$ egrep -xn 'programadora?' wordlist-preao-20150102.txt
776176:programador
776177:programadora
</pre>
<h3>Filtragem <em>case-insensitive</em></h3>
<p>Para fazer filtragem <em>case-insensitive</em> (ignorando diferenças entre maiúsuclas e minúsculas), usamos a opção <b><code>-i</code></b>:</p>
<pre lang="bash">$ egrep -i 'marcel' wordlist-preao-20150102.txt
Marcelino
Marcelismo
Marcelismos
Marcelista
Marcelistas
Marcelo
</pre>
<p>Buscamos por &#8220;marcel&#8221;, mas os resultados se iniciam por letras maiúsculas. Se retirarmos a opção -i, nenhum resultado será exibido.</p>
<h3>Filtrando por linhas que <em>não</em> coincidem com o padrão</h3>
<p>Para filtrar por linhas que <strong>NÃO</strong> coincidem com o padrão, usamos a opção <code>-v</code>:</p>
<pre lang="bash">$ egrep -v 'programador' wordlist-preao-20150102.txt
</pre>
<p>Esse comando exibe todas as linhas que <strong>não</strong> coincidam com o padrão &#8220;programador&#8221;. Não incluí a saída do comando, pois possui milhares de linhas.</p>
<h3>Exibindo linhas anteriores a um padrão</h3>
<p>Além de exibir apenas a linha que coincide com o padrão do filtro, podemos exibir as linhas imediatamente anteriores à linha que coincidiu com o padrão. Para isso, usamos a opção <code>-B NUM</code> (B de <em>before</em>), onde <code>NUM</code> é o número de linhas que devem ser exibidor.</p>
<pre lang="bash">$ egrep -nx -B 2 'programador' wordlist-preao-20150102.txt
776174-programadas
776175-programado
776176:programador
</pre>
<p>Nesse comando, filtro pela linha que contém exatamente a palavra &#8220;programador&#8221; (opção <code>-x</code>), exibindo, também, os números de linha (opção <code>-n</code>). Com a opção <code>-B 2</code>, são exibidas as duas linhas anteriores à linha onde há a palavra &#8220;programador&#8221;.</p>
<h3>Exibindo linhas posteriores a um padrão</h3>
<p>De forma semelhante ao que ocorre com a opção <code>-B NUM</code>, é possível exibir as linhas posteriores. Usa-se a opção <code>-A NUM</code> (A de <em>after</em>).</p>
<pre lang="bash">$ egrep -nx -A 2 'programador' wordlist-preao-20150102.txt
776176:programador
776177-programadora
776178-programadoras
</pre>
<h3>Exibindo linhas anteriores e posteriores a um padrão</h3>
<p>Podemos mostrar as linhas anteriores e posteriores, se juntarmos as opções -A e -B. Porém, há uma forma mais simples, usando a opção <code>-C</code>, desta forma:</p>
<pre lang="bash">$ egrep -nx -C 2 'programador' wordlist-preao-20150102.txt
776174-programadas
776175-programado
776176:programador
776177-programadora
776178-programadoras
</pre>
<p>Isso equivale a usar as opções -A e -B juntas, desta forma:</p>
<pre lang="bash">$ egrep -nx -A 2 -B 2 'programador' wordlist-preao-20150102.txt
776174-programadas
776175-programado
776176:programador
776177-programadora
776178-programadoras
</pre>
<h3>Colorindo o trecho que coincide com o padrão</h3>
<p>Usando a opção <code>--color</code> (ou <code>--colour</code>, no inglês britânico) é possível destacar os trechos que coincidiram com o padrão. Por exemplo:</p>
<pre lang="bash">$ egrep --color 'programador' wordlist-preao-20150102.txt
desprogramador
desprogramadora
desprogramadoras
desprogramadores
programador
programadora
programadoras
programadores
reprogramador
reprogramadora
reprogramadoras
reprogramadores
</pre>
<p>Você verá que todas as ocorrências de &#8220;programador&#8221; nessas strings estarão destacadas (em vermelho, provavelmente).</p>
<h3>Busca recursiva</h3>
<p>Para exemplificar a busca recursiva, vou duplicar o arquivo de dicionário, criando os arquivos <code>wordlist-preao-20150102_2.txt</code> e <code>wordlist-preao-20150102_3.txt</code>. Vou deixá-los no mesmo diretório. Mas, como a busca será recursiva, eles poderiam estar em qualquer nível abaixo do diretório corrente.</p>
<p>Para realizar buscas recursivas, usarmos a opção <code>-r</code> ou <code>-R</code>. Desta vez, não vamos informar um nome de arquivo. Em vez disso, passaremos o nome di um diretório. No exemplo abaixo, uso o diretório corrente (<code>.</code>).</p>
<pre lang="bash">$ egrep -rx 'programador' .
./wordlist-preao-20150102.txt:programador
./wordlist-preao-20150102_2.txt:programador
./wordlist-preao-20150102_3.txt:programador
</pre>
<p>Quando a busca é recursiva, antes da linha é sempre exibido o nome do arquivo onde o padrão foi encontrado.</p>
<h3>Exibindo apenas o nome do arquivo onde o padrão foi encontrado</h3>
<p>Com a busca recursiva, às vezes apenas queremos saber em qual arquivo existe um determinado padrão, sem exibir as linhas. Para isso, basta usar a opção <code>-l</code>, desta forma:</p>
<pre lang="bash">$ egrep -rl 'programador' .
./wordlist-preao-20150102.txt
./wordlist-preao-20150102_2.txt
./wordlist-preao-20150102_3.txt
</pre>
<h2>Conclusão</h2>
<p>A ferramenta <code>grep</code> é bem completa, permitindo fazer buscar bem complexas, usando Expressões Regulares.</p>
<p>É possível juntar várias opções (dentre as que mostrei e diversas outras do <code>grep</code>) e realizar buscas de forma rápida e ágil.</p>
<h3>Dica para Programadores</h3>
<p>Uma combinação de parâmetros que acho muito útil no dia-a-dia de programação é a <code>-irn</code>. Muitas vezes preciso procurar onde alguma string está presente e em quais arquivos. Por isso faço uma busca <strong>r</strong>ecursiva, <em>case-<strong>in</strong>sensitive</em>, mostrando o número da linha onde o padrão foi encontrado. Por exemplo:</p>
<pre lang="bash">$ egrep -irn 'string' .
</pre>
<p>&nbsp;</p>
<p>Para aprender mais sobre Comandos Linux e Shell Script, veja meu curso <a title="Shell Script Para Programadores" href="http://shellparaprogramadores.com.br"><strong style="font-size: 1.2em;">Shell Script Para Programadores</strong></a>.</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/grep-como-buscar-em-arquivos-linux/">grep: como buscar em arquivos no Linux</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/grep-como-buscar-em-arquivos-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1070</post-id>	</item>
		<item>
		<title>find: como encontrar arquivos no Linux</title>
		<link>http://rberaldo.com.br/find-como-encontrar-arquivos-linux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=find-como-encontrar-arquivos-linux</link>
					<comments>http://rberaldo.com.br/find-como-encontrar-arquivos-linux/#respond</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Sun, 11 Jan 2015 21:47:51 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Shell Script (Bash)]]></category>
		<category><![CDATA[Bash]]></category>
		<category><![CDATA[comando]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[Shell]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1068</guid>

					<description><![CDATA[<p>Buscar arquivos tem ficado cada vez mais fácil usando interface gráfica. Porém, há momentos em que os filtros oferecidos pelas interfaces não são suficientes. Além disso, caso você esteja gerenciando um servidor Linux via SSH, não terá interface gráfica e terá de usar o (muito) bom e velho comando find. O comando find permite buscar [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/find-como-encontrar-arquivos-linux/">find: como encontrar arquivos no Linux</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1076 size-medium" src="http://rberaldo.com.br/wp-content/uploads/2015/01/find-300x113.jpg" alt="find: como encontrar arquivos no Linux" width="300" height="113" srcset="http://rberaldo.com.br/wp-content/uploads/2015/01/find-300x113.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/01/find-150x56.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/01/find-133x50.jpg 133w, http://rberaldo.com.br/wp-content/uploads/2015/01/find-624x235.jpg 624w, http://rberaldo.com.br/wp-content/uploads/2015/01/find.jpg 800w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>Buscar arquivos tem ficado cada vez mais fácil usando interface gráfica. Porém, há momentos em que os filtros oferecidos pelas interfaces não são suficientes. Além disso, caso você esteja gerenciando um servidor Linux via SSH, não terá interface gráfica e terá de usar o (muito) bom e velho comando <code>find</code>.</p>
<p>O comando <code>find</code> permite buscar arquivos filtrando por nome, tamanho, data, dono, grupo, permissões, tipo e outros. A busca é recursiva, por padrão, mas pode ser restringida a uma determinada profundidade. Em suma, o <code>find</code> é uma ferramenta bem completa e poderosa.</p>
<p><span id="more-1068"></span></p>
<p><strong>Nota</strong>: Este artigo é um a versão reduzida do artigo bônus do curso <a title="Shell Script Para Programadores" href="http://shellparaprogramadores.com.br"><strong>Shell Script Para Programadores</strong></a>. Para conhecer melhor o curso e fazer sua matrícula, <a title="Shell Script Para Programadores" href="http://shellparaprogramadores.com.br"><strong>clique aqui</strong></a>.</p>
<p>&nbsp;</p>
<p>Uma nota importante. Vou falar muito em <strong>arquivos</strong>. Vale lembrar que, no Linux e em outros sistemas Unix-Like (como o Mac OS X), diretórios e links simbólicos também são tratados como arquivos. Logo, quando eu citar <strong>arquivo</strong>, isso também vai incluir diretórios e links.</p>
<h2>Sintaxe do comando find</h2>
<p>A sintaxe do comando <code>find</code> é a seguinte:</p>
<pre lang="bash">find local_da_busca criterios_da_busca acoes
</pre>
<p>Os arquivos encontrados são exibidos na saída padrão. Se nenhum arquivo for encontrado, nada é exibido.</p>
<p>Antes de mostrar exemplos práticos de uso, é importante listar as opções mais comuns do <code>find</code>.</p>
<h2>Opções do comando find</h2>
<p>Assim como diversas outras ferramentas e comandos do Linux, o <code>possui</code> inúmeras opções e parâmetros. Vou mostrar aqui as mais frequentemente utilizadas e conhecidas.</p>
<ul>
<li><code>-maxdepth NUM</code>: altera o nível da profundidade da busca;</li>
<li><code>-regextype TYPE</code>: altera o tipo de expressão regular utilizada pelas opções <code>-regex</code> e <code>-iregex</code>;</li>
<li><code>-amin n</code>: o arquivo foi acessado <code>n</code> minutos atrás;</li>
<li><code>-atime n</code>: O arquivo foi acessado nos últimos <code>n</code> dias (<code>n</code> é multiplicado por 24 horas automaticamente);</li>
<li><code>-ctime n</code>: O arquivo foi modificado nos últimos <code>n</code> dias (<code>n</code> é multiplicado por 24 horas automaticamente);</li>
<li><code>-empty</code>: Arquivo ou diretório está vazio;</li>
<li><code>-gid n</code>: Arquivo cujo número do grupo do dono é <code>n</code>;</li>
<li><code>-group gname</code>: Arquivo pertence ao grupo <code>gname</code>;</li>
<li><code>-iname pattern</code>: Igual a <code>-name</code>, porém é <em>case-insensitive</em> (não diferencia maiúsculas e minúsculas);</li>
<li><code>-iregex pattern</code>: Igual a <code>-regex</code>, porém é <em>case-insensitive</em> (não diferencia maiúsculas e minúsculas);</li>
<li><code>-name pattern</code>: Arquivos cujo nome contenha <code>pattern</code>;</li>
<li><code>-perm mode</code>: As permissões do arquivo (em octal) correspondem a <code>perm</code>;</li>
<li><code>-perm -mode</code>: As permissões do arquivo estão no padrão definido por <code>-mode</code>. É possível filtrar por <code>-perm -g=w</code>, por exemplo. Uma forma mais genérica e menos restrita que usar <code>-perm perm</code>;</li>
<li><code>-regex pattern</code>: Nome do arquivo coincide com a expressão regular <code>pattern</code>;</li>
<li><code>-size n[UNIDADE]</code>: O arquivo ocupa <code>n</code> unidades de armazenamento. As unidades incluem <code>k</code> para kilobyte, <code>M</code> para megabyte e <code>G</code> para gigabyte;</li>
<li><code>-type c</code>: Arquivo é do tipo <code>c</code>. Dentre os tipos válidos estão <code>f</code> para arquivo, <code>d</code> para diretório e <code>l</code> para link simbólico;</li>
<li><code>-uid n</code>: Arquivo cujo dono tem ID <code>n</code>;</li>
<li><code>-user username</code>: Arquivo cujo dono é <code>username</code>;</li>
<li>Ações</li>
</ul>
<p>Além de filtrar por nome, tipo, dono etc, é possível realizar ações com os arquivos encontrados. As principais são:</p>
<ul>
<li><code>-delete</code>: Remove o arquivo encontrado;</li>
<li><code>-exec command ;</code>: executa uma ação (comando) com o arquivo;</li>
<li><code>-ok command ;</code>: Semelhante a <code>-exec command ;</code>, mas pede permissão ao usuário antes de executar o comando;</li>
</ul>
<h2>Exemplos de Uso do Comando find</h2>
<p>Agora que já vimos as principais opções e parâmetros, vamos a exemplos práticos.</p>
<h3>O exemplo mais básico</h3>
<p>O exemplo mais simples é o seguinte:</p>
<pre lang="bash">$ find .
</pre>
<p>Esse comendo lista todos os arquivos, de forma recursiva, a partir do diretório atual (<code>.</code>).</p>
<h3>Filtrando por nome de arquivo, usando string</h3>
<p>Para filtrar por nome de arquivo, usamos a opção <code>-name</code>. Para ignorar diferenças entre maiúsculas e minúsculas, usamos <code>-iname</code>.</p>
<pre lang="bash">$ find / -name "hosts"
</pre>
<p>Esse comando procura por arquivos com o nome &#8220;hosts&#8221; em todo o sistema de arquivos (<code>/</code>). Se você executar como usuário normal (sem ser <em>root</em>), verá vários erros como estes:</p>
<pre lang="plain">find: `/root': Permission denied
find: `/etc/ssl/private': Permission denied
</pre>
<p>Essas mensagens são enviadas para a saída de erro. Logo, podemos eliminá-las, redirecionando a saída de erros para <code>/dev/null</code>, desta forma:</p>
<pre lang="bash">$ find / -name "hosts" 2&gt; /dev/null
</pre>
<p>Para realizar buscas <em>case-insensitive</em>, basta usar <code>-iname</code>, desta forma:</p>
<pre lang="bash">$ find / -iname "hosts" 2&gt; /dev/null
</pre>
<h3>Filtrando por extensão de arquivo</h3>
<p>Também usaremos <code>-name</code> (ou <code>-iname</code>) para isso. Basta usar o asterisco, desta forma:</p>
<pre lang="bash">$ find / -name '*.conf'
</pre>
<p>Pordemos fazer um <code>OR</code> (<code>OU</code>) no comando <code>find</code>, usando a opção <code>-o</code>. Isso é válido para diversos outros parâmetros, não apenas o <code>-name</code>, desta forma:</p>
<pre lang="bash">$ find / -name '*.ini' -o -name '*.conf'
</pre>
<h3>Filtrando por nome de arquivo, usando Expressões Regulares</h3>
<p>É possível usar Expressões Regulares (ERs) para a filtragem. Se você não conhece Expressões Regulares, é bom agilizar e começar a ler o <a href="http://aurelio.net/regex/guia" target="_blank"><strong>Expressões Regulares &#8211; Guia de Consulta Rápida</strong></a>, do <strong>Aurelio Marinho Jargas</strong>, <a href="http://aurelio.net/regex/guia" target="_blank">disponibilizado <em>online</em></a> e gratuitamente pelo próprio autor.</p>
<p>A filtragem por ERs, ao contrário da filtragem por string, é feita em todo o caminho (<em>path</em>) do arquivo. Ou seja, se quiser encontrar o arquivo <code>./fubar3</code>, você pode usar as ERs <code>.*bar.' ou <code>.*b.*3</code>, porém não poderá usar <code>f.*r3</code>, pois ela não coincidirá com o padrão <code>./</code> no início do <em>path</em>.</code></p>
<p>Por exemplo, o seguinte comando não retornará saída alguma:</p>
<pre lang="bash">$ find / -regex "hosts" 2&gt; /dev/null
</pre>
<p>Já o seguinte comando retornará resultados:</p>
<pre lang="bash">$ find / -regex ".*hosts" 2&gt; /dev/null
/etc/hosts
/etc/avahi/hosts
/etc/exim4/conf.d/router/150_exim4-config_hubbed_hosts
/home/beraldo/.ssh/known_hosts
</pre>
<h3>Alterando o Tipo das Expressões Regulares</h3>
<p>O comando <code>find</code> suporta diversos tipos de Expressões Regulares (ERs). São eles: <code>emacs</code> (que é o tipo padrão), <code>posix-awk</code>, <code>posix-basic</code>, <code>posix-egrep</code> e <code>posix-extended</code>.</p>
<p>Para alterar o tipo das ERs, usamos a opção <code>-regextype TIPO</code>.</p>
<p>O tipo padrão (<code>emacs</code>) não suporta alguns recursos, como quantificadires. Para mostrar isso na prática, criei um arquivo chamado <code>aaarquivo</code> (com 3 letras &#8220;a&#8221;) no diretório atual. Vamos testar os seguintes comandos:</p>
<pre lang="bash">$ find . -regex ".*a{3}rquivo"
</pre>
<p>O comando acima não retorna resultados, pois os quantificadores não são interpretados. Porém, se mudarmos o tipo das ERs para <code>posix-egrep</code>, o resultado será exibido, conforme o comando abaixo.</p>
<pre lang="bash">$ find . -regextype posix-egrep -regex ".*a{3}rquivo"
./aaarquivo
</pre>
<p>Para mais detalhes sobre ERs e o padrão <code>posix-egrep</code> veja o meu post <a title="grep: como buscar em arquivos no Linux" href="http://rberaldo.com.br/grep-como-buscar-em-arquivos-linux/"><strong>grep: como buscar em arquivos no Linux</strong></a>.</p>
<h3>Filtrando por tipo de arquivo</h3>
<p>É possível filtrar por tipo de arquivo (arquivo, diretório, link simbólico etc), usando a opção <code>-type</code>.</p>
<h4>Filtrando apenas por arquivos</h4>
<p>Para filtrar apenas por arquivos, usamos o opção <code>-type f</code>:</p>
<pre lang="bash">$ find /usr/bin -type f
</pre>
<h4>Filtrando apenas por diretórios</h4>
<p>Para filtrar apenas por diretórios, usamos o opção <code>-type d</code>:</p>
<pre lang="bash">$ find /usr -type d
</pre>
<h4>Filtrando apenas por links simbólicos</h4>
<p>Para filtrar apenas por links simbólicos, usamos o opção <code>-type l</code>:</p>
<pre lang="bash">$ find /usr/bin -type l
</pre>
<p>Há outros tipos disponíveis, porém pouco utilizados. Veja o manual (<code>man find</code>) para ver todas as possibilidades.</p>
<p>[cta id=&#8217;925&#8242;]</p>
<h3>Filtrando por data</h3>
<p>Para filtrar por data de modificação, usamos a opção <code>-mtime</code>. Vamos a alguns exemplos.</p>
<pre lang="bash"># arquivos modificados entre agora e 1 dia atrás (últimas 24 horas)
$ find . -mtime 0

# arquivos modificados a menos de um dia (últimas 24 horas, igual ao comando anterior)
$ find . -mtime -1 

# arquivos modificados entre 24 e 48 horas atrás
$ find . -mtime 1

# arquivos modificados há mais de 48 horas
$ find . -mtime +1

# Arquivos modificados entre 6 e 9 monutos atrás
$ find . -mmin +5 -mmin -10 
</pre>
<p>A mesma lógica é usada nos outros parâmetros de busca por data, como <code>-atime</code>.</p>
<h3>Filtrando por nome de usuário</h3>
<pre lang="bash">$ find /home/ -user beraldo
</pre>
<h3>Filtranso por grupo</h3>
<pre lang="bash">$ find / -group nome_do_grupo
</pre>
<h3>Filtranso por tamanho de arquivo</h3>
<p>O comando a seguir busca por arquivos com mais de 2 MB.</p>
<pre lang="bash">$ find . -size +2M
</pre>
<p>Este comando buscar por arquivos com, exatamente, 2MB:</p>
<pre lang="bash">$ find . -size 2M
</pre>
<p>Por fim, este busca por arquivos com menos de 2MB:</p>
<pre lang="bash">$ find . -size -2M
</pre>
<p>O comando a seguir lista arquivos maiores que 50MB e menores que 100MB.</p>
<pre lang="bash">$ find / -size +50M -size -100M
</pre>
<h3>Filtrando por permissão</h3>
<p>Filtrando por arquivos com permissão 644:</p>
<pre lang="bash">$ find . -perm 664
</pre>
<p>Este comando filtra por arquivos com permissão, no mínimo, 644. Ou seja, arquivos com mais permissões também serão exibidos (incluindo arquivos com permissão 777, por exemplo):</p>
<pre lang="bash">$ find . -perm -664
</pre>
<p>O comando a seguir filtra por arquivos que tenham permissão de escrita (número 2, em octal) para algum usuário (o próprio dono, o grupo ou outros usuários):</p>
<pre lang="bash">$ find . -perm /222
</pre>
<p>Os 3 comandos a seguir se comportam da mesma forma. São listados arquivos que possuam permissão de escrita pelo dono ou pelo grupo (OU não exclusivo).</p>
<pre lang="bash">$ find . -perm /220 
$ find . -perm /u+w,g+w 
$ find . -perm /u=w,g=w
</pre>
<p>Estes 2 comandos abaixo se comportam da mesma forma. Eles listam arquivos que possuam permissão de escrita pelo dono <strong>e</strong> pelo grupo:</p>
<pre lang="bash">$ find . -perm -220 
$ find . -perm -g+w,u+w
</pre>
<p>Os 2 comandos abaixo também se comportam da mesma forma. Ele lista arquivos que possam ser lidos por todos (<code>-perm -444</code> ou <code>-perm -a+r</code>), possuem ao menos um bit de escrita, podendo ser escrito pelo dono, grupo ou outros (<code>-perm /222</code> ou <code>-perm /a+w</code>), porém não pode ser executado por ninguém (<code>! -perm /111</code> ou <code>! -perm /a+x</code>).</p>
<pre lang="bash">$ find . -perm -444 -perm /222 ! -perm /111 
$ find . -perm -a+r -perm /a+w ! -perm /a+x
</pre>
<p>Para mais detalhes sobre permissões, veja o meu post <a title="CHMOD: Permissões em Sistemas Linux e Unix-Like" href="http://rberaldo.com.br/chmod-permissoes-em-sistemas-linux-e-unix-like/">CHMOD: Permissões em Sistemas Linux e Unix-Like</a>.</p>
<h2>Executando Ações Com os Arquivos Encontrados pelo find</h2>
<p>É possível executar ações com os arquivos encontrados pelo comando <code>find</code>.</p>
<p>A sintaxe é a seguinte:</p>
<pre lang="bash">$ find diretorio opcoes -exec comando {} \;
</pre>
<p>Os caracteres <code>{}</code> serão trocados automaticamente pelo arquivo encontrado.</p>
<p>Por exemplo, para executarmos <code>ls -ldh &lt;arquivo&gt;</code> para cada arquivo encontrado no diretório atual, fazemos o seguinte:</p>
<pre lang="bash">$ find . -maxdepth 1 -type f -exec ls -lhd {} \;
</pre>
<p>Além do <code>-exec</code>, existe o <code>-ok</code>, que se comporta da mesma forma, porém, antes de executar o comando, pergunta ao usuário. É útil para prevenir a execução de comandos errados. Imagine que você executa um <code>rm</code> no arquivo errado&#8230;</p>
<pre lang="bash">$ find . -maxdepth 1 -type f -ok ls -lhd {} \;
&lt; ls ... ./a &gt; ? y
-rw-r--r-- 1 beraldo beraldo 0 Jan 17 14:41 ./a
&lt; ls ... ./b &gt; ? y
-rw-r--r-- 1 beraldo beraldo 0 Jan 17 14:41 ./b
&lt; ls ... ./c &gt; ? y
-rw-r--r-- 1 beraldo beraldo 0 Jan 17 14:41 ./c
</pre>
<p>Para confirmar a execução, digite <code>y</code> (de <em>yes</em>).</p>
<h3>Removendo arquivos encontrados</h3>
<p>Em vez de usar o comando <code>rm</code> no <code>-exec</code>, é possível usar diretamente a opção <code>-delete</code>, que remove os arquivos encontrados. Por exemplo:</p>
<pre lang="bash">$ find . -maxdepth 1 -type f -delete
</pre>
<p>Porém as remoções serão feitas sem a confirmação do usuário. Se desejar que seja perguntado, use <code>-ok</code>, como mostrado anteriormente.</p>
<h2>Conclusão</h2>
<p>O comando <code>find</code> faz buscas bem mais detalhadas que as buscas feitas pela interface gráfica. É um ferramenta muito versátil e poderosa.</p>
<p>Há diversas outras opções e parâmetros, além dos que mostrei aqui. Veja o manual (<code>man find</code>) para mais detalhes. Mostrei aqui apenas os mais utilizados no dia-a-dia.</p>
<p>Para aprender mais sobre Comandos Linux e Shell Script, veja meu curso <a title="Shell Script Para Programadores" href="http://shellparaprogramadores.com.br"><strong style="font-size: 1.2em;">Shell Script Para Programadores</strong></a>.</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/find-como-encontrar-arquivos-linux/">find: como encontrar arquivos no Linux</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/find-como-encontrar-arquivos-linux/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1068</post-id>	</item>
		<item>
		<title>Cache com PHP usando APC</title>
		<link>http://rberaldo.com.br/cache-com-php-usando-apc/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cache-com-php-usando-apc</link>
					<comments>http://rberaldo.com.br/cache-com-php-usando-apc/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Sat, 10 Jan 2015 12:02:53 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[apc]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[desempenho]]></category>
		<category><![CDATA[performance]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=1059</guid>

					<description><![CDATA[<p>Desemepnho de aplicações é cada vez mais importante. A Web está mais cheia de conteúdo a cada dia. E, consequentemente, as páginas tendem a possuir mais dados. Se não tomarmos cuidado com o desempenho, nossos sistemas ficarão lentos. Uma forma de contornar esse problema é fazer cache de dados usados com frequência. Há várias maneiras [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/cache-com-php-usando-apc/">Cache com PHP usando APC</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-1385 size-full" src="http://rberaldo.com.br/wp-content/uploads/2015/01/php-apc.jpg" alt="Cache com PHP usando APC" width="470" height="246" srcset="http://rberaldo.com.br/wp-content/uploads/2015/01/php-apc.jpg 470w, http://rberaldo.com.br/wp-content/uploads/2015/01/php-apc-150x79.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2015/01/php-apc-300x157.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2015/01/php-apc-96x50.jpg 96w" sizes="(max-width: 470px) 100vw, 470px" /></p>
<p>Desemepnho de aplicações é cada vez mais importante. A Web está mais cheia de conteúdo a cada dia. E, consequentemente, as páginas tendem a possuir mais dados. Se não tomarmos cuidado com o desempenho, nossos sistemas ficarão lentos.</p>
<p>Uma forma de contornar esse problema é fazer <strong><em>cache</em></strong> de dados usados com frequência. Há várias maneiras de fazer <em>cache</em> com PHP. Neste artigo, vou falar do <strong>APC</strong> (<em>Alternative PHP Cache</em>), que é uma extensão do próprio PHP muito simples de usar.</p>
<p><span id="more-1059"></span></p>
<h2>O Que é Cache?</h2>
<p>Segundo a <a title="Artigo da Wikipedia sobre Cache" href="http://pt.wikipedia.org/wiki/Cache" target="_blank">Wikipedia</a>, cache é &#8220;um dispositivo de acesso rápido, interno a um sistema, que serve de intermediário entre um operador de um processo e o dispositivo de armazenamento ao qual esse operador acede&#8221;. Ou seja, cache é um local de rápido acesso a informações que ficam salvas em um dispositovo cujo acesso é mais lento.</p>
<p>Por exemplo, um arquivo em disco pode ter seu conteúdo armazenado em cache na memória. O tempo de acesso à memória é muito mais rápido que o de acesso ao disco. Por isso é útil fazer cache em memória de arquivos acessados frequentemente.</p>
<h2>O Que é o APC?</h2>
<p>APC (<em>Alternative PHP Cache</em>) é uma extensão do PHP. Ela faz cache de dados em memória. Basta dizer qual será a &#8220;chave&#8221; (um identificador único para o dado salvo), qual é a informação a ser salva e por quanto tempo ela deve ser mantida em cache. O resto é tarefa do PHP.</p>
<p>A extensão APC não vem habilitada por padrão. É necessário habilitá-la em seu php.ini, ou instalar o pacote correspondente, caso tenha instalado o PHP a partir dos pacotes para Linux ou Mac OS X.</p>
<h2>Como Usar o APC Para Fazer Cache com PHP</h2>
<p>Existem <a title="Lista de funções do APC" href="http://php.net/manual/pt_BR/book.apc.php" target="_blank">algumas funções do APC</a>, mas vou me ater às seguintes:</p>
<ul>
<li><a title="Documentação da função apc_add" href="http://php.net/manual/pt_BR/function.apc-add.php" target="_blank"><code>apc_add</code></a>: adiciona um dado ao cache, caso ainda não esteja salvo;</li>
<li><a title="Documentação da função apc_clear_cache" href="http://php.net/manual/pt_BR/function.apc-clear-cache.php" target="_blank"><code>apc_clear_cache</code></a>: limpa o cache do APC;</li>
<li><a title="Documentação da função apc_delete" href="http://php.net/manual/pt_BR/function.apc-delete.php" target="_blank"><code>apc_delete</code></a>: remove um valor do cache;</li>
<li><a title="Documentação da função apc_exiss" href="http://php.net/manual/pt_BR/function.apc-exists.php" target="_blank"><code>apc_exists</code></a>: verifica se uma determinada chave existe no cache;</li>
<li><a title="Documentação da função apc_fetch" href="http://php.net/manual/pt_BR/function.apc-fetch.php" target="_blank"><code>apc_fetch</code></a>: retorna um valor salvo no cache;</li>
<li><a title="Documentação da função apc_store" href="http://php.net/manual/pt_BR/function.apc-store.php" target="_blank"><code>apc_store</code></a>: salva um valor no cache, sobrescrevendo-o, caso já exista.</li>
</ul>
<h3>Adicionando um Valor ao Cache</h3>
<p>Para adicionar um valor ao cache, é possível usar <code>apc_add</code> ou <code>apc_store</code>. A única diferença entre essas duas funções é que apc_add adiciona um dado ao cache apenas se ele ainda não existir. Já apc_store sempre adiciona o dado. Consequentemente, apc_store vai sobrescrever a informação, caso ela já tenha sido armazenada anteriormente.</p>
<p>A sintaxe de ambas as funções é a mesma, desta forma:</p>
<pre lang="php">bool apc_add ( string $key , mixed $var [, int $ttl ] )
bool apc_store ( string $key , mixed $var [, int $ttl ] )
</pre>
<p>O parâmetro <code>$key</code> é a chave de identificação para a informação no cache. É esse valor que usaremos para buscar ou remover o dado do cache. O parâmetro <code>$var</code> é o valor a ser armazenado no cache. Ele pode ser uma simples variável, um array ou mesmo um objeto. E o parâmetro <code>$ttl</code> (<em>Time To Live</em>) é o tempo, em segundos, que o dado deve permanecer em cache. Se <code>$ttl</code> não for especificado (ou for <code>0</code>), o dado será mantido em cache até que seja manualmente removido.</p>
<p>Para exemplificar, vamos inserir alguns dados no cache, todos com tempo de vida de 60 segundos:</p>
<pre lang="php">$a = 'valor a';
apc_add( 'chave_a', $a, 60 );

$arr = [
    'a' => 1,
    'b' => 2
];
apc_add( 'meu_array', $arr, 60 );

$obj = new stdClass;
$obj->nome = 'Beraldo';
apc_add( 'meu_objeto', $obj, 60 );
</pre>
<h3>Retornando Dados Salvos no Cache</h3>
<p>Para retornar um dado salvo no cache, usamos a função <code>apc_fetch</code>. Basta passar como parâmetro a chave que utilizamos em <code>apc_add</code> ou em <code>apc_store</code>.</p>
<pre lang="php">$a = apc_fetch( 'chave_a' );
var_dump( $a );

$arr = apc_fetch( 'meu_array' );
var_dump( $arr );

$obj = apc_fetch( 'meu_objeto' );
var_dump( $obj );
</pre>
<p>Se os dados estiverem em cache, <code>var_dump</code> os exibirá. Caso contrário, será retornado FALSE.</p>
<h3>Verificando a Existência de um Dado no Cache</h3>
<p>Antes de retornar o dado com <code>apc_fetch</code>, podemos usar <code>apc_exists</code> para verificar se a chave existe no cache. Assim, podemos alterar o trecho anterior pelo seguinte.</p>
<pre lang="php">if ( apc_exists( 'chave_a' ) )
{
    $a = apc_fetch( 'chave_a' );
    var_dump( $a );
}
else
{
    echo "Chave chave_a não está no cache";
}


if ( apc_exists( 'meu_array' ) )
{
    $arr = apc_fetch( 'meu_array' );
    var_dump( $arr );
}
else
{
    echo "Chave meu_array não está no cache";
}

if ( apc_exists( 'meu_objeto' ) )
{
    $obj = apc_fetch( 'meu_objeto' );
    var_dump( $obj );
}
else
{
    echo "Chave meu_objeto não está no cache";
}
</pre>
<h3>Removendo Um Dado do Cache</h3>
<p>Para remover um dado específico, usamos <code>apc_delete</code>.Basta passar a chave por parâmetro, desta forma:</p>
<pre lang="php">apc_delete( 'chave_a' );
apc_delete( 'meu_array' );
apc_delete( 'meu_objeto' );
</pre>
<h3>Limpando Todo o Cache</h3>
<p>Para limpar o cache completamente, basta usar a função <code> apc_clear_cache</code>:</p>
<pre lang="php">apc_clear_cache();
</pre>
<p>Dessa forma, todos os dados salvos em cache serão apagados.</p>
<h2>Comparando Desempenho</h2>
<p>Para mostrar a diferença de tempo entre acessar um dado em disco e outro dado em cache, vou mostrar uma comparação de desempenho entre ambos.</p>
<p>Para isso, usarei um arquivo <code>.ini</code>, que é geralmente utilizado para armazenar configurações do sistema. Caso você não saiba trabalhar com arquivos <code>.ini</code> usando o PHP, recomendo que leia <a title="Arquivos .ini: processando arquivos de configuração com PHP" href="http://rberaldo.com.br/arquivos-ini-processando-arquivos-de-configuracao-com-php/">este meu post</a>, onde mostro como fazer isso.</p>
<h3>Critério de Avaliação</h3>
<p>Para avaliar o desempenho, usarei apenas o tempo de execução da tarefa em questão. Usarei a função <a href="http://php.net/microtime" target="_blank"><code>microtime</code></a>, que retorna a hora atual, em microssegundos. Tendo a hora de início e a hora de término, basta subtraí-las e teremos o tempo de execução total. Vou considerar apenas o tempo de acesso ao dispositivo (disco e cache), sem considerar o tempo para exibir o dado na tela. Para exibir o resultado, usarei <a href="http://php.net/number_format" target="_blank"><code>number_format</code></a>, pois, quando o tempo é muito pequeno, o número é exibido em notação científica (no formato 5.124E-10) e pode confundir quem não está habituado a visualizar números nesse formato.</p>
<h3>Arquivo de Configuração</h3>
<p>Primeiramente, crie um arquivo chamado <code>config.ini</code>, com o seguinte conteúdo:</p>
<pre lang="ini">[db]
host = "localhost"
user = "usuario"
pass = "senha"
dbname = "nome_do_banco"
</pre>
<p>Esse é um simples exemplo de um arquivo <code>.ini</code>, com configurações para acesso a um banco de dados.</p>
<h3>Carregando Dados do Arquivo</h3>
<p>Vaamos agora criar o script que carrega uma configuração diretamente do arquivo.</p>
<pre lang="php">$configFile = 'config.ini';

$start = microtime( true );
$config = parse_ini_file( $configFile, true );
$host = $config[ 'db' ][ 'host' ];
$end = microtime( true );

var_dump( $host );
var_dump( number_format( $end - $start, 20 ) );
</pre>
<p>No meu computador, o tempo de execução exibido foi <strong>0.00008392333984375000</strong>.</p>
<h3>Carregando Dados do Cache</h3>
<p>Nesse script, vamos carregar o conteúdo do arquivo <code>.ini</code> e salvá-lo no cache. Apenas depois disso vamos contabilizar o tempo. Afinal, estamos interessados apenas no tempo de acesso ao cache.</p>
<pre lang="php">$configFile = 'config.ini';
$configArr = parse_ini_file( $configFile, true );

apc_store( 'config', $configArr, 5 );

$start = microtime( true );
$config = apc_fetch( 'config' );
$host = $config[ 'db' ][ 'host' ];
$end = microtime( true );

var_dump( $host );
var_dump( number_format( $end - $start, 20 ) );
</pre>
<p>O resultado retornado foi <strong>0.00001096725463867188</strong>.</p>
<h3>Comparando os Resultados</h3>
<p>O tempo de execução do primeiro script foi de <strong>0.00008392333984375000</strong> segundos. O segundo levou <strong>0.00001096725463867188</strong>. Se dividirmos ambos os números, veremos que o script que acessa o cache rodou, aproximadamente, <strong>7.652174</strong> vezes mais rápido!</p>
<h2>Conclusão</h2>
<p>O uso de cache acelera bastante a execução dos nossos sistemas.</p>
<p>O APC é apenas uma das opções de cache para PHP. Existem diversas outras. Não importa muito qual você usará, mas é importante que seja usado cache para armazenar informações que são acessadas com frequência, como dados de um arquivo de configuração, como usei no exemplo.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/cache-com-php-usando-apc/">Cache com PHP usando APC</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/cache-com-php-usando-apc/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1059</post-id>	</item>
		<item>
		<title>Bootstrapping com PHP e Arquivo de Inicialização</title>
		<link>http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=bootstrapping-php-arquivo-inicializacao</link>
					<comments>http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Sat, 27 Dec 2014 23:11:04 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[boot]]></category>
		<category><![CDATA[bootstrapping]]></category>
		<category><![CDATA[inicialização]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=949</guid>

					<description><![CDATA[<p>&#160; Neste post vou lhe mostrar como fazer o bootstrapping (ou boot) de sua aplicação PHP. Vamos criar um arquivo de inicialização, que vai ser executado em todas as requisições. Isso vai garantir que a execução ocorra da forma correta, evitando erros. Essa prática é muito importante pois ela garante integridade ao seu sistema. Seguindo esse [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/">Bootstrapping com PHP e Arquivo de Inicialização</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter wp-image-850 size-medium" src="http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-300x157.png" alt="Bootstrapping com PHP e Arquivo de Inicialização" width="300" height="157" srcset="http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-300x157.png 300w, http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-150x78.png 150w, http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_-95x50.png 95w, http://rberaldo.com.br/wp-content/uploads/2014/10/800px-PHP-n_logo.svg_.png 800w" sizes="(max-width: 300px) 100vw, 300px" /></p>
<p>&nbsp;</p>
<p>Neste post vou lhe mostrar como fazer o <em>bootstrapping</em> (ou <em>boot</em>) de sua aplicação PHP. Vamos criar um arquivo de inicialização, que vai ser executado em todas as requisições. Isso vai garantir que a execução ocorra da forma correta, evitando erros.</p>
<p>Essa prática é muito importante pois ela garante integridade ao seu sistema. Seguindo esse modelo, é possível centralizar as configurações do sistema. Assim, sempre que precisar alterar uma configuração, basta fazer isso em um único arquivo, e ela se refletirá em toda a aplicação.</p>
<p><span id="more-949"></span></p>
<h2>Mas o que é <em>Bootstrapping</em>, afinal?</h2>
<p>A palavra <em><a title="Artigo sobre Boot na Wikipedia" href="http://pt.wikipedia.org/wiki/Boot" target="_blank">bootstraping</a></em> significa um processo de inicialização. É comum falarmos sobre <em>boot</em> do Sistema Operacional. Porém também podemos fazer <em>bootstrap</em> (ou <em>boot</em>) de nossas aplicações, sejam elas em PHP ou em outras linguagens. Vou mostrar um exemplo usando PHP, mas a lógica é a mesma para qualquer outra linguagem.</p>
<p>&nbsp;</p>
<h2>Estrutura da Aplicação</h2>
<p>É necessário que todas as requisições à sua aplicação sejam processadas por um único arquivo (geralmente index.php), que, conforme a URL, chama outros scripts ou métodos.</p>
<p>Essa é a abordagem usada nas <a href="http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/" target="_blank">URLs Amigáveis</a> ou nas <a href="http://pt-br.html.net/tutorials/php/lesson10.php" target="_blank">Query Strings</a>.</p>
<p>Caso você ainda não use esta técnica, recomendo ler <a href="http://rberaldo.com.br/urls-amigaveis-sem-htaccess-usando-slim/" target="_blank">este meu artigo</a>.</p>
<h2>Exemplo de Arquivo de Bootstrapping</h2>
<p>Vamos criar um script (<code>init.php</code>), que faz basicamente duas coisas:</p>
<ol>
<li>Define configurações do PHP para toda a aplicação;</li>
<li>Cria constantes que serão usadas na aplicação.</li>
</ol>
<p>Um simples exemplo é o seguinte:</p>
<p>&nbsp;</p>
<pre lang="php">
<?php 

/* =============================
   Configurações do PHP
   =========================== */

// define valores padrão para diretivas do php.ini
ini_set( 'error_reporting', -1 );
ini_set( 'display_errors', 0 ); // deve ser definida para zero (0) em ambiente de produção

// timezone
date_default_timezone_set( 'America/Sao_Paulo' );


// tempo máximo de execução de um script
set_time_limit( 60 );



/* ======================================
   Cria constantes usadas na aplicação
   =================================== */

// conexão com base de dados
define( 'BD_SERVIDOR', 'localhost' );
define( 'BD_USUARIO', 'usuario' );
define( 'BD_SENHA', 'senha' );
define( 'BD_NOME', 'nome_banco' );

// conexão SMTP
define( 'SMTP_SERVIDOR', 'mail.servidor.com.br' );
define( 'SMTP_USUARIO', 'usuario' );
define( 'SMTP_SENHA', 'senha' );
</pre>
<p>O exemplo é simples. Porém mostra a ideia geral do <em>bootstrapping</em>.</p>
<p>Salve o script como <code>init.php</code>. Dê um <code>require_once</code> nele em seu <code>index.php</code>. Dessa forma, todas as requisições vão passar pelo init.php, garantindo a integridade da aplicação.</p>
<p>Também é possível separar o init.php em arquivos menores. Por exemplo, um para configurações do PHP, outro para configurações de acesso a bancos de dados, outro para SMTP e assim por diante. Apenas lembre-se de dar um <code>require_once</code> em todos eles no init.php.</p>
<h2>Melhorando o Script de <em>Bootstrapping</em></h2>
<p>Vamos melhorar o script de <em>bootstrapping</em>, fazendo duas alterações principais:</p>
<ol>
<li>Passar as configurações do PHP para outro arquivo;</li>
<li>Usar um arquivo <code>.ini</code> para guardar as configurações de banco de dados, SMTP etc</li>
</ol>
<p>Arquivos <code>.ini</code> são muito usados para configurações. E o melhor: <a title="Arquivos .ini: processando arquivos de configuração com PHP" href="http://rberaldo.com.br/arquivos-ini-processando-arquivos-de-configuracao-com-php">o PHP pode manipular arquivos <code>.ini</code> nativamente</a>.</p>
<p>Crie o arquivo <code>php-config.php</code> (ou outro nome que preferir) com o seguinte conteúdo:</p>
<pre lang="php">
<?php

// define valores padrão para diretivas do php.ini
ini_set( 'error_reporting', -1 );
ini_set( 'display_errors', 0 ); // deve ser definida para zero (0) em ambiente de produção

// timezone
date_default_timezone_set( 'America/Sao_Paulo' );


// tempo máximo de execução de um script
set_time_limit( 60 );
</pre>
<p>Nesse arquivo você poderá incluir outras configurações do PHP que forem necessárias para seu projeto.</p>
<p>Vamos também criar um arquivo chamado <code>config.ini</code>, com este conteúdo:</p>
<pre lang="ini">; Configurações de banco de dados
[db]
host = "localhost"
user = "usuario"
pass = "senha"
dbname = "nome_do_banco"


; Dados do SMTP
[smtp]
host = "smtp.servidor.com.br"
user = "usuario"
pass = "senha"
</pre>
<p><strong style="color: red;">ATENÇÃO</strong>: O ideal é manter o <code>config.ini</code> fora da pasta pública (geralmente <code>www</code> ou <code>public_html</code>) do seu servidor. Assim não será possível acessar o arquivo pela URL e seus dados estarão seguros.</p>
<p>Precisaremos também de uma função para buscar os dados no arquivo ini. Para isso, vou usar a seguinte função:</p>
<pre lang="php">function getConfig( $configName )
{
    $configFile = '../config.ini';

    $config = parse_ini_file( $configFile, true );

    list( $section, $param ) = explode( '.', $configName );

    if ( array_key_exists( $section, $config ) )
    {
        if ( array_key_exists( $param, $config[ $section ] ) )
        {
            return $config[ $section ][ $param ];
        }
    }

    return null;
}
</pre>
<p>A função recebe como parâmetro uma string no formato <code>secao.configuracao</code> e busca o valor correspondente no arquivo ini. Por exemplo, para buscar o valor do parâmetro <code>host</code> da seção <code>db</code>, basta executar <code>getConfig( 'db.host' )</code>.<br />
Se o valor não existir, é retornado <code>null</code></p>
<p>Para mais detalhes sobre como manipular arquivos ini com PHP, veja <a title="Arquivos .ini: processando arquivos de configuração com PHP" href="http://rberaldo.com.br/arquivos-ini-processando-arquivos-de-configuracao-com-php">este post</a>.</p>
<p>Nosso <code>init.php</code> ficará assim:</p>
<pre lang="php"><?php

require_once 'php-config.php';


function getConfig( $configName )
{
    $configFile = '../config.ini';

    $config = parse_ini_file( $configFile, true );

    list( $section, $param ) = explode( '.', $configName );

    if ( array_key_exists( $section, $config ) )
    {
        if ( array_key_exists( $param, $config[ $section ] ) )
        {
            return $config[ $section ][ $param ];
        }
    }

    return null;
}
</pre>
<h2>Otimização Usando Cache</h2>
<p>Acesso a disco é uma tarefa muito lenta, que exige muito da CPU. O tempo de acesso a um dado em disco pode levar até 100.000 vezes mais tempo que um acesso à memória (veja o artigo <a href="http://queue.acm.org/detail.cfm?id=1563874" target="_blank"><em>The Pathologies of Big Data</em></a> para mais detalhes). Esse número pode variar de diversas formas. Estou citando o pior caso.</p>
<p>É importante fazer cache da dados acessados frequentemente. Se você nunca trabalhou com cache em PHP, sugiro que leia <a title="Cache com PHP usando APC" href="http://rberaldo.com.br/cache-com-php-usando-apc/" target="_blank">este meu post</a>, onde mostro como usar a biblioteca APC para fazer cache de dados.</p>
<p>Vou rescrever a função <code>getConfig</code>, usando cache. Usarei a técnica do "Carregamento Preguiçoso" (ou <em>Lazy Load</em>, em inglês), de forma que só vou carregar os dados no cache quando for necessário buscar uma informação pela primeira vez. Dessa forma, podemos economizar alguns milissegundos no carregamento da página, caso ela não precise, imediatamente, de algum dado do arquivo de configuração.</p>
<p>Vou incluir alguns dados de <em>debug</em>, para evidenciar a diferença no desempenho. Nosso arquivo <code>index.php</code> ficará assim:</p>
<pre lang="php"><?php
require_once 'php-config.php';

// limpa o cache inicialmente, apenas para nosso teste de desempenho
apc_clear_cache();
 
function getConfig( $configName )
{
    // chave utilizada no APC para identificar o array $config no cache
    $apcConfigKey = 'app_config';
    
    // horário inicial, para nosso teste de desempenho
    $start = microtime( true );
    
    if ( ! apc_exists( $apcConfigKey ) )
    {
        echo "Buscando no arquivo...";
        
        $configFile = '../config.ini';
 
        $config = parse_ini_file( $configFile, true );

        // armazena em cache por 15 minutos (900 segundos)
        apc_store( $apcConfigKey, $config, 900 ); 
    }
    else
    {
        echo "Buscando no cache...";

        $config = apc_fetch( $apcConfigKey );
    }
    
    list( $section, $param ) = explode( '.', $configName );
 
    if ( array_key_exists( $section, $config ) )
    {
        if ( array_key_exists( $param, $config[ $section ] ) )
        {
            // tempo de execução total
            $time = microtime( true ) - $start;
            echo "Tempo total: " . number_format( $time, 20 );

            return $config[ $section ][ $param ];
        }
    }

    return null;
}

// Buscando dois dados, para comparar o tempo de acesso ao disco e ao cache
var_dump( getConfig( 'db.host' ) );
var_dump( getConfig( 'db.user' ) );
</pre>
<p>Se você executar o arquivo <code>index.php</code>, verá uma saída parecida com a seguinte:</p>
<pre lang="plain">Buscando no arquivo... 
Tempo total: 0.00008201599121093750
string 'localhost' (length=9)

Buscando no cache... 
Tempo total: 0.00001502037048339844
string 'usuario' (length=7)
</pre>
<p>Se dividirmos os tempo de execução, veremos que o tempo de acesso ao dado em cache é mais de 5 vezes menor.</p>
<p>Testes feitos, cache aprovado. Vamos retirar os trechos de teste de desempenho e de <em>debug</em>. Nosso <code>index.php</code> ficará desta forma, pronto para ser usado em produção:</p>
<pre lang="php"><?php
require_once 'php-config.php';
 
function getConfig( $configName )
{
    $apcConfigKey = 'app_config';
    
    if ( ! apc_exists( $apcConfigKey ) )
    {
        $configFile = '../config.ini';
 
        $config = parse_ini_file( $configFile, true );

        // armazena em cache por 15 minutos (900 segundos)
        apc_store( $apcConfigKey, $config, 900 ); 
    }
    else
    {
        $config = apc_fetch( $apcConfigKey );
    }
    
 
    list( $section, $param ) = explode( '.', $configName );
 
    if ( array_key_exists( $section, $config ) )
    {
        if ( array_key_exists( $param, $config[ $section ] ) )
        {
            return $config[ $section ][ $param ];
        }
    }

    return null;
}
</pre>
<h2>Dicas Avançadas</h2>
<p>É possivel melhorar bastante esse arquivo de <em>boostrapping</em>, adicionando <a href="http://php.net/manual/pt_BR/function.spl-autoload-register.php" target="_blank">Autoload</a> e <a href="http://rberaldo.com.br/composer-php/" target="_blank">Composer</a>, por exemplo.</p>
<p>Não pretendo entrar em detalhes sobre isso, visto que este post tem o objetivo de mostrar algo simples, porém prático e útil.</p>
<p>Caso queira ver um exemplo mais completo, <a href="http://www.binpress.com/tutorial/php-bootstrapping-crash-course/146" target="_blank">veja este link</a> (em inglês), onde são usados Autoload e Composer no arquivo de <em>Bootstrapping</em>.</p>
<p>No Curso <a href="http://www.ultimatephp.com.br/curso/" target="_blank">ULTIMATE PHP</a>, no capítulo final, mostro passo-a-passo como montar uma aplicação utilizando, dentre outras técnicas, o conceito de <em>Bootstrapping</em>. Vou ensinar, em detalhes, como criar uma aplicação segura, estável e eficiente. <a href="http://www.ultimatephp.com.br/curso/" target="_blank">Clique aqui para conhecer melhor o curso</a>.</p>
<p>&nbsp;<br />

<div class="uphp_post_cta uphp_course_excerpt" style="margin-bottom: 2.3em;">
<h2>Aprenda Ainda Mais</h2>

<div class="uphp_cta_image">
	<img src="http://www.ultimatephp.com.br/wp-content/uploads/2015/10/3d-cover-2-01-291x500.png" alt="15 Dicas, Boas Práticas e Fundamentos do PHP" width="180">
</div>

<div class="uphp_cta_text">
	<p>Conheça Dicas <strong>FUNDAMENTAIS</strong> para programar em PHP de forma Profissional</p>
    
    <p>Não se considere Programador PHP sem antes ler este guia e adotar estas práticas!</p>

	<p>Baixe <strong>gratuitamente</strong> este guia com 15 Dicas de PHP</p>

	<div class="btn-download">
    	<a href="http://www.ultimatephp.com.br/guia/" target="_blank">
        	<img src="http://blog.ultimatephp.com.br/wp-content/uploads/2015/11/btn-baixar-agora.png" alt="Baixar Agora">
        </a>
    </div>
</div>

<div style="clear: both;"></div>
</div>
	</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/">Bootstrapping com PHP e Arquivo de Inicialização</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/bootstrapping-php-arquivo-inicializacao/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">949</post-id>	</item>
		<item>
		<title>A Magia dos números de Fibonacci</title>
		<link>http://rberaldo.com.br/a-magia-dos-numeros-de-fibonacci/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-magia-dos-numeros-de-fibonacci</link>
					<comments>http://rberaldo.com.br/a-magia-dos-numeros-de-fibonacci/#respond</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Mon, 11 Nov 2013 11:18:32 +0000</pubDate>
				<category><![CDATA[Dicas]]></category>
		<category><![CDATA[Entretenimento]]></category>
		<category><![CDATA[Vídeos]]></category>
		<category><![CDATA[fibonacci]]></category>
		<category><![CDATA[golden ratio]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[mathmagic]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=776</guid>

					<description><![CDATA[<p>Na semana passada, foi publicado no Canal do TED Talk no Youtube, o vídeo The magic of Fibonacci numbers, no qual Arthur Benjamin mostra a Sequência de Fibonacci e a magia escondida nela. Se as escolas mostrassem esse lado da Matemática, muitas crianças poderiam se interessar mais por essa área do conhecimento. Vale a pena [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/a-magia-dos-numeros-de-fibonacci/">A Magia dos números de Fibonacci</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><img loading="lazy" class="aligncenter size-full wp-image-778" alt="Espiral de Fibonacci" src="http://rberaldo.com.br/wp-content/uploads/2013/11/fibonacci-spiral.gif" width="450" height="280" /><br />
Na semana passada, foi publicado no <a title="Acessar o canal do TED Talks no Youtube" href="http://www.youtube.com/user/TEDtalksDirector?feature=watch" target="_blank">Canal do TED Talk no Youtube</a>, o vídeo <em><strong>The magic of Fibonacci numbers</strong></em>, no qual <strong>Arthur Benjamin</strong> mostra a Sequência de Fibonacci e a magia escondida nela.</p>
<p>Se as escolas mostrassem esse lado da Matemática, muitas crianças poderiam se interessar mais por essa área do conhecimento.</p>
<p>Vale a pena assistir.</p>
<p><iframe src="//www.youtube.com/embed/SjSHVDfXHQ4" height="315" width="560" allowfullscreen="" frameborder="0"></iframe></p>
<p>A Disney também já falou desse tema, em <strong>Pato Donald no País da Matemágica</strong>.</p>
<p><iframe src="//www.youtube.com/embed/wbftu093Yqk" height="315" width="560" allowfullscreen="" frameborder="0"></iframe></p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/a-magia-dos-numeros-de-fibonacci/">A Magia dos números de Fibonacci</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/a-magia-dos-numeros-de-fibonacci/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">776</post-id>	</item>
		<item>
		<title>C/C++: calculando hash MD5 usando a biblioteca do OpenSSL</title>
		<link>http://rberaldo.com.br/cc-calculando-hash-md5-usando-a-biblioteca-do-openssl/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=cc-calculando-hash-md5-usando-a-biblioteca-do-openssl</link>
					<comments>http://rberaldo.com.br/cc-calculando-hash-md5-usando-a-biblioteca-do-openssl/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Thu, 29 Nov 2012 13:35:31 +0000</pubDate>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Dicas]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[criptografia]]></category>
		<category><![CDATA[crypt]]></category>
		<category><![CDATA[hash]]></category>
		<category><![CDATA[md5]]></category>
		<category><![CDATA[openssl]]></category>
		<category><![CDATA[segurança]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=695</guid>

					<description><![CDATA[<p>Obter o hash MD5 de uma string é uma tarefa bem simples em algumas linguagens de mais alto nível, como Python, Ruby ou PHP. Porém, em C e C++ não é tão simples. Sem o auxílio de uma biblioteca externa, não podemos calcular hashes, como MD5 ou SHA-1 (exceto se você implementar esses algoritmos, é [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/cc-calculando-hash-md5-usando-a-biblioteca-do-openssl/">C/C++: calculando hash MD5 usando a biblioteca do OpenSSL</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp.jpg"><img loading="lazy" class="aligncenter size-full wp-image-702" title="C/C++" src="http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp.jpg" alt="C/C++" width="315" height="314" srcset="http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp.jpg 315w, http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp-150x150.jpg 150w, http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp-300x300.jpg 300w, http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp-50x50.jpg 50w, http://rberaldo.com.br/wp-content/uploads/2011/01/c_cpp-100x100.jpg 100w" sizes="(max-width: 315px) 100vw, 315px" /></a></p>
<p>Obter o hash MD5 de uma string é uma tarefa bem simples em algumas linguagens de mais alto nível, como Python, Ruby ou PHP. Porém, em C e C++ não é tão simples. Sem o auxílio de uma biblioteca externa, não podemos calcular hashes, como MD5 ou SHA-1 (exceto se você implementar esses algoritmos, é claro).</p>
<p>Mostrarei adiante como calcular o hash MD5 de uma string, utilizando a biblioteca OpenSSL, disponível nos sistemas Linux e Unix-Like (em Mac OS X também funciona, apesar de aparecerem warnings dizendo que as funções da OpenSSL são obsoletas).</p>
<p><span id="more-695"></span></p>
<pre lang="c" line="1">
#include <stdio.h>
#include <stdlib.h>
#include <openssl/evp.h>

/**
 * Função que retorna o hash MD5 de uma string
 *
 * @param input String cujo MD5 queremos calcular
 * @param output String onde será escrito o MD5 (deve estar previamente alocada)
 */
char * md5FromString( char *input, char *output )
{
    EVP_MD_CTX mdctx;
    const EVP_MD *md;
    unsigned int output_len, i;
    unsigned char uOutput[EVP_MAX_MD_SIZE];

    /* Initialize digests table */
    OpenSSL_add_all_digests();

    /* You can pass the name of another algorithm supported by your version of OpenSSL here */
    /* For instance, MD2, MD4, SHA1, RIPEMD160 etc. Check the OpenSSL documentation for details */
    md = EVP_get_digestbyname( "MD5" );

    if ( ! md )
    {
        printf( "Unable to init MD5 digest\n" );
        exit( 1 );
    }

    EVP_MD_CTX_init( &mdctx );
    EVP_DigestInit_ex( &mdctx, md, NULL );
    EVP_DigestUpdate( &mdctx, input, strlen( input ) );

    EVP_DigestFinal_ex( &mdctx, uOutput, &output_len );
    EVP_MD_CTX_cleanup( &mdctx );

    // zera a string antes de começar a concatenação
    strcpy( output, "" );
    for(i = 0; i < output_len; i++)
    {
        sprintf( output, "%s%02x", output, uOutput[i] );
    }

    return output;
}


main(int argc, char *argv[])
{
    char output[33]; // 32 caracteres mais um para o \0

    if ( argc != 2 )
    {
        fprintf( stderr, "Erro. Uso: %s \n", argv[0] );
        exit( 1 );
    }

    printf( "MD5( '%s' ) = %s\n", argv[1], md5FromString( argv[1], output ) );

    return 0;
}
</pre>
<p>Esse código foi adaptado a partir <a href="http://ivbel.blogspot.com.br/2012/02/how-to-calculate-md5-hash-value-using.html" target="_blank">deste post</a>, once encontrei uma forma simples e objetiva de calcular o hash.</p>
<p>Para compilar, é necessário linkar com a biblioteca do OpenSSL, com a opção <code>-lcrypto</code>, conforme o exemplo abaixo:</p>
<pre lang="bash">gcc md5.cpp  -lcrypto -o md5
</pre>
<p>Para executar, passe como parâmetro a string cujo MD5 deseja-se calcular:</p>
<pre lang="bash">$ ./md5 "string a ser convertida em hash"
</pre>
<p>Espero que tenham gostado da dica. :)</p>
<h3>Dicas de Livros</h3>
<p>O livro escrito pelos criadores da linguagem C: <a href="http://links.lomadee.com/ls/VWpCMjtSdU1QQkdwZTsyNTI5MTAyODswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">C - a Linguagem de Programacao Padrao Ansi - Kernighan, Brian / Ritchie, Dennis M</a><br />
<a href="http://links.lomadee.com/ls/UjRFNztuWW5MekhfSTsyNTI5MTAzMjswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">C - Completo e Total - Schildt, Herbert </a><br />
<a href="http://links.lomadee.com/ls/MnBxajt2clpiV1czNzsyNTI5MTAzODswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">C Como Programar 6 Edicao - Paul; Deitel Harvey Deitel </a><br />
<a href="http://links.lomadee.com/ls/V1JaNTtvX345WVZoYjsyNTI5MTA0MDswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">Linguagem C - Luís Damas</a></p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/cc-calculando-hash-md5-usando-a-biblioteca-do-openssl/">C/C++: calculando hash MD5 usando a biblioteca do OpenSSL</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/cc-calculando-hash-md5-usando-a-biblioteca-do-openssl/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">695</post-id>	</item>
		<item>
		<title>Git: criando repositórios remotos</title>
		<link>http://rberaldo.com.br/git-criando-repositorios-remotos/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=git-criando-repositorios-remotos</link>
					<comments>http://rberaldo.com.br/git-criando-repositorios-remotos/#comments</comments>
		
		<dc:creator><![CDATA[Roberto Beraldo]]></dc:creator>
		<pubDate>Fri, 23 Nov 2012 08:32:26 +0000</pubDate>
				<category><![CDATA[CVS]]></category>
		<category><![CDATA[Dicas]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Software Livre]]></category>
		<category><![CDATA[cvs]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[remote]]></category>
		<category><![CDATA[remoto]]></category>
		<category><![CDATA[repositorio]]></category>
		<category><![CDATA[repository]]></category>
		<category><![CDATA[ssh]]></category>
		<guid isPermaLink="false">http://rberaldo.com.br/?p=646</guid>

					<description><![CDATA[<p>Há um tempo, eu mostrei aqui como usar as funcionalidades básicas do Git para controlar versões de softwares. Hoje mostrarei como criar repositórios remotos via SSH. É possível usar repositórios remotos por meio do GitHub ou do Google Code, mas às vezes queremos ter um repositório remoto para uso próprio, que seja fechado, sem que [&#8230;]</p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/git-criando-repositorios-remotos/">Git: criando repositórios remotos</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a href="http://rberaldo.com.br/wp-content/uploads/2012/11/git_logo.png"><img loading="lazy" class="aligncenter size-medium wp-image-648" title="Git" src="http://rberaldo.com.br/wp-content/uploads/2012/11/git_logo-300x125.png" alt="Git" width="300" height="125" srcset="http://rberaldo.com.br/wp-content/uploads/2012/11/git_logo-300x125.png 300w, http://rberaldo.com.br/wp-content/uploads/2012/11/git_logo-150x62.png 150w, http://rberaldo.com.br/wp-content/uploads/2012/11/git_logo-119x50.png 119w, http://rberaldo.com.br/wp-content/uploads/2012/11/git_logo.png 910w" sizes="(max-width: 300px) 100vw, 300px" /></a></p>
<p>Há um tempo, <a title="Git: controlando versão de seus programas" href="http://rberaldo.com.br/git-controlando-versao-de-seus-programas/" target="_blank">eu mostrei aqui</a> como usar as funcionalidades básicas do Git para controlar versões de softwares. Hoje mostrarei como criar repositórios remotos via SSH.</p>
<p>É possível usar repositórios remotos por meio do <a title="GitHub" href="http://github.com" target="_blank">GitHub</a> ou do <a title="Google Code" href="http://code.google.com" target="_blank">Google Code</a>, mas às vezes queremos ter um repositório remoto para uso próprio, que seja fechado, sem que ninguém mais possa ter acesso a ele.</p>
<p>Para isso, você precisará ter acesso a um servidor Linux (ou outro Unix-Like) com servidor SSH, o qual hospedará seus repositórios.</p>
<p><span id="more-646"></span></p>
<p><!-- LOMADEE - BEGIN --></p>
<div align="center"><script type="text/javascript" language="javascript">// <![CDATA[
lmd_source="25276785";
	lmd_si="33488276";
	lmd_pu="22470430";
	lmd_c="BR";
	lmd_wi="468";
	lmd_he="60";
// ]]&gt;</script><br />
<script src="http://image.lomadee.com/js/ad_lomadee.js" type="text/javascript" language="javascript"></script></div>
<p><!-- LOMADEE - END --></p>
<h3> Servidor Remoto para o repositório Git</h3>
<p>Acesse seu servidor via SSH, escolha um diretório para armazenar seus repositórios e cria sub-diretórios para cada repositório. Para isso, faça o seguinte:</p>
<p>Suponha que você escolheu o diretório <code>~/git</code> (diretório <code>git</code> na sua <em>home</em>) e que vamos criar um repositório chamado <code>exemplo1</code>. Logo, executaremos os seguintes comandos:</p>
<pre lang="bash">mkdir ~/git
cd ~/git
mkdir exemplo1.git
cd exemplo1.git</pre>
<p>Com o diretório criado, devemos defini-lo como um repositório remoto, que apenas armazenará arquivos, sem diretório de trabalho (<em>working directory</em>):</p>
<pre lang="bash">git --bare init</pre>
<p>Com isso, você já tem um repositório remoto, ao qual pode empurrar código (comando <code>push</code>) e de onde pode fazer clone.</p>
<div align="center"><!-- LOMADEE - BEGIN --><br />
<script type="text/javascript" language="javascript">// <![CDATA[
lmd_source="25276793";
	lmd_si="33488276";
	lmd_pu="22470430";
	lmd_c="BR";
	lmd_wi="468";
	lmd_he="60";
// ]]&gt;</script><br />
<script src="http://image.lomadee.com/js/ad_lomadee.js" type="text/javascript" language="javascript"></script></div>
<p><!-- LOMADEE - END --></p>
<h3>Repositório Git Local</h3>
<p>Na sua máquina local, você deve fazer o seguinte:</p>
<pre lang="bash">mkdir meu-repositorio
cd meu-repositorio
git init .
touch README
git add .
git commit -a -m "primeiro commit"</pre>
<p>Até aqui nada que não sabíamos: apenas criamos um diretório para ser nosso repositório e o definimos como um repositório. Também criamos um arquivo README, colocando-o no repositório e fazendo um commit.</p>
<p>Agora é necessário especificar que será usado um repositório remoto, onde podemos fazer push dos arquivos. Para isso, usamos o seguinte comando:</p>
<pre lang="bash">git remote add origin ssh://usuario@servidor.com/~/git/examplo1.git</pre>
<p>Altere o comando com seu nome de usuário e endereço do servidor. Caso tenha alterado o caminho ao arquivo exemplo1.git, altere-o nesse comando também.</p>
<p>Após isso, basta empurrar os arquivos ao servidor remoto:</p>
<pre lang="bash">git push origin master
</pre>
<p>A partir daí, você pode fazer alterações e commitá-las, sempre lembrando de fazer um push após os commits:</p>
<pre lang="bash">git push
</pre>
<p>Caso queira clonar o repositório em outra máquina, basta clonar o repositório, conforme abaixo:</p>
<pre lang="bash">git clone ssh://usuario@servidor/~/git/exemplo1.git
</pre>
<p>Simples, né? :)</p>
<h3>Dicas de Livros</h3>
<p>Seguem abaixo alguns links de bons livros sobre Linux:</p>
<p><a href="http://links.lomadee.com/ls/ZFhnVzs3M0J1c0pYSTsyNTI3NjcxNjswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">Linux &#8211; Guia Prático &#8211; Carlos Morimoto</a><br />
<a href="http://links.lomadee.com/ls/bnJHXztPM0liTDBpYzsyNTI3NjcyOTswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">Certificação Linux Lpi &#8211; Nível 1 Exames 101 e 102 &#8211; Steven Pritchard, Bruno Pessanha</a><br />
<a href="http://links.lomadee.com/ls/Y29PNTs4bVZJX2Z0MjsyNTI3NjczNzswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">Certificação Linux Lpi: Nível 2 Exames 201 e 202 &#8211; Steven Pritchard, Bruno Gomes Pessanha, Nicolai Langfeldt</a><br />
<a href="http://links.lomadee.com/ls/Nk5mfjt5OEpNOVVuaTsyNTI3Njc0NDswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">Comandos do Linux &#8211; Prático e Didático &#8211; Marco Agisander Lunardi</a><br />
<a href="http://links.lomadee.com/ls/aUw5eDs0fmRES2ladzsyNTI3Njc1MTswOzE3NjszMzQ4ODI3NjswO0JSOzM7.html" target="_blank">Programação Shell Linux &#8211; 5º Ed. 2005 &#8211; Julio Cezar Neves</a></p>
<p>O post <a rel="nofollow" href="http://rberaldo.com.br/git-criando-repositorios-remotos/">Git: criando repositórios remotos</a> apareceu primeiro em <a rel="nofollow" href="http://rberaldo.com.br">Blog do Beraldo</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://rberaldo.com.br/git-criando-repositorios-remotos/feed/</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">646</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/

Object Caching 67/403 objects using disk
Page Caching using disk: enhanced (Page is feed) 
Minified using disk
Database Caching using disk

Served from: rberaldo.com.br @ 2020-10-17 18:10:31 by W3 Total Cache
-->