Bacharel em Informática com Ênfase em Análise de Sistemas pela Universidade Estácio de Sá, Petrópolis-RJ. Experiência de quase 3 anos com PHP, tendo atuado como analista programador em diversos projetos do setor público e privado e no treinamento de profissionais. Atualmente é programador analista na Mais Empresas Tecnologia da Informação, em Campo Grande-MS.
Olá, amigos leitores! Gostaria hoje de separar um tempinho para falar das funções de controle de saída do PHP (Output Control)... O objetivo deste artigo é apresentar alguns exemplos de como usar essas funções para realizar algumas tarefas práticas e adaptações em códigos PHP.
Bom, a maioria dessas funções começam com "ob", de "output buffering". O que elas fazem é basicamente permitir a você controlar como e quando as saídas ( echos, print e outras funções que tenha saída) vão ser enviadas ou não para o browser. Volta e meia passava por essas funções em meus passeios pelo Manual do PHP (acreditem, o Manual do PHP tem uma visão linda, façam mais passeios por lá...), até que um dia resolvi utilizá-las. Depois de usá-las em alguns lugares, percebi que elas são bem úteis<!--more-->, principalmente quando você precisa fazer certas "gambiarras" em alguns casos... :) Para quem não está familiarizado com o termo, costuma-se chamar de "gambiarra" qualquer adaptação não convencional nos códigos, um atalho, remendo.
Não estou encorajando aqui o uso de gambiarras bagunçadas. Excesso de gambiarras faz os códigos ficarem de difícil manutenção e com mais chance de erros; porém em alguns casos precisamos fazer pequenas adaptações, adequadamente documentadas, como por exemplo quando temos que trabalhar com bibliotecas externas prontas "caixa preta" que possuem recursos mais limitados ou com sistemas prontos, ou quando se deseja resolver um problema em pouco tempo pra depois desenvolver uma solução definitiva. Enfim, é bom conhecer soluções desse tipo pra usar quando necessário e para identificar quando algum outro programador usou.
O que é "saída" e "buffer"?
Quem já estiver familiarizado com estes termos, pode pular essa parte. Para quem ainda tem dúvidas, só pra explicar: "saída" é tudo aquilo que o script PHP envia para o usuário quando executado. Se estiver executando o PHP em modo linha de comando, a saída será exibida em texto no shell. Se o script foi chamado através de uma URL para um servidor web, a saída será o código enviado para o browser. Ou seja, todo echo, print, saídas da tag do php para o modo HTML, tudo que você manda o PHP exibir e tudo que ele exibe (mesmo que você não peça, com por exemplos os erros) é saída. Outro termo que estou mencionando aqui é o "buffer". "Buffer" significa uma área de memória utilizada para gravar dados temporários, durante alguma operação, no nosso caso ele armazena as saídas que queremos manipular até que digamos para para gravar. Understood?
OB na prática
A utilização destes recursos consiste basicamente em definir um ponto do código a partir do qual toda a saída do script fica sendo armazenada em memória, e depois definir outros pontos aonde você diz o que fazer com esse conteúdo que ficou armazenado, seja guardar, tratar, descartar ou liberar para o usuário que requisitou a informação. Vou explicar aqui como funcionam as principais dessas funções OB apresentando alguns exemplos práticos:
1 - Tenho uma função que joga um conteúdo para a saída, ao invés de apenas retornar, mas gostaria de armazenar essa saída dela em uma variável:
PHP
<?php /* Acima, a função que retorna o que estiver guardado no buffer e desativa a gravação do buffer, ou seja, a partir daqui tudo o que está guardado, ao invés de ir direto para o usuário, é retornado para a variável $conteudo_arquivo e tudo volta ao normal. Se você não fizer alguma coisa para mostrar esse conteúdo o usuário nunca terá acesso a ele. Sobre a variável $conteudo_arquivo, agora você pode fazer qualquer coisa com ela... */ ?>www.revistaphp.com.br
Note que, para este caso específico de leitura de arquivo eu poderia fazer de outro jeito, usei essa função apenas para exemplificar.
2 - Quero fazer um include de um arquivo que emite saídas e quero capturar essas saídas para uma variável.
PHP
<?php // Para este caso, podemos utilizar o mesmo princípio do exemplo anterior: include("meu_arquivo_com_saidas.inc.php"); ?>www.revistaphp.com.br
3 - No exemplo anterior, e se eu quisesse simplesmente garantir que a saída do meu arquivo include venha... sem links? Sim, tirar todos os links do conteúdo, deixando apenas o texto e mostrar na tela. Hum... será que dá? Vamos ver...:
PHP
<?php include("meu_arquivo_com_saidas.inc.php"); // Inclui o arquivo que vai gerar o conteúdo $conteudo = ob_get_clean(); // Peguei o conteúdo do buffer, joguei na variável $conteudo, limpei o buffer e parei de armazenar // Até aqui tudo ok, e agora? /// Bom, para tirar os links podemos utilizar uma expressão regular. Não vou entrar em detalhes sobre ER aqui; para entender melhor recomendo consultar o Guia do Aurélio Verde, em http://guia-er.sourceforge.net/. // E voilá! Mostramos nosso conteúdo com os links retirados... echo $conteudo; ?>www.revistaphp.com.br
O importante nesse exemplo é entender que você pode manipular como quiser o conteúdo da saída antes de enviá-lo ao usuário.
4 - Quero realizar uma operação que exija que nenhum conteúdo seja enviado para o usuário antes dela, mas estou incluindo um arquivo que emite saídas antes. Isso é um situação comum... Digamos que você tem um arquivo cabecalho_padrao.inc.php que possui alguns echos e saídas HTML, que você inclui em todas as telas e que por algum motivo não pode mexer nele. Acontece que nesse caso você quer enviar um session_start() depois de executá-lo, assim:
PHP
<?php include("cabecalho.inc.php"); ?>www.revistaphp.com.br
Fazendo desta forma acima vai dar um erro como este abaixo, porque nenhuma saída pode ser enviada antes do session_start():
PHP
Warning: session_start(): Cannot send session cookie - headers already sent by (output started at g:\weblocal\www\testes\ob\cabecalho.inc.php:3) in <b>g:\weblocal\www\testes\ob\teste4.php</b> on line <b>5</b><br /> Warning: session_start(): Cannot send session cache limiter - headers already sent (output started at g:\weblocal\www\testes\ob\cabecalho.inc.php:3) in <b>g:\weblocal\www\testes\ob\teste4.pwww.revistaphp.com.br
Resolvendo o problema com as funções OB, vai ficar assim:
PHP
<?php include("cabecalho.inc.php"); ob_end_flush(); // Função que libera pra o usuário tudo o que estiver gravado no buffer e pára de armazenar. Agora sim, pode jogar tudo... ?>www.revistaphp.com.br
5 - Quero pegar uma saída de alguma coisa para jogar em um template Smarty.
PHP
<?php echo "olá"; include("arquivo_com_saidas.inc.php"); $template = new Smarty_MeuSistema(); // Instancia um objeto Smarty já configurado $template->assign("texto",$conteudo); // Envia para o template $template->display("meu_template.tpl"); ?>www.revistaphp.com.br
Para mais informações sobre Smarty, vide http://smarty.php.net/.
6 - Quero dar uma opção de converter o conteúdo de minhas páginas HTML para PDF, utilizando uma dessas classes disponíveis.
Neste exemplo estarei trabalhando com a html2pdf, uma classe baseada na FPDF. Na verdade estou baseando este exemplo em um outro do próprio site dela.
PHP
<?php echo "Olá!!" include("pagina_com_conteudos.php"); ?> Conteúdo conteúdo conteúdo... <?php require_once('libs/html2pdf/html2fpdf.php'); $pdf = new HTML2FPDF(); $pdf->AddPage(); $pdf->SetMargins(10,10,10); $pdf->WriteHTML($conteudo_html); $pdf->Output('minha_pagina.pdf','I'); ?> www.revistaphp.com.br
E se eu quiser ter uma alternativa pra mostrar as páginas como HTML somente quando solicitado, utilizando uma variável passada por GET? Vamos lá...:
PHP
<?php if($_GET["exibir_pdf"]]) echo "Olá!!" include("pagina_com_conteudos.php"); ?> Conteúdo conteúdo conteúdo... <?php if($_GET["exibir_pdf"]]) { require_once('libs/html2pdf/html2fpdf.php'); $pdf = new HTML2FPDF(); $pdf->AddPage(); $pdf->SetMargins(10,10,10); $pdf->WriteHTML($conteudo_html); $pdf->Output('minha_pagina.pdf','I'); } ?> www.revistaphp.com.br
Agora para chamar a página em pdf você só precisa chamar "http://seu_servidor/url_do_php.php?exibir_pdf=1". Utilizando esse recurso você pode até colocar um link no rodapé de suas páginas "ver em pdf"... Legal né?
Só uma observação importante: diferente de quando você vai jogando a saída direto para o usuário, quando guardamos a saída em um buffer vai sendo tudo armazenado temporariamente na memória do servidor. Portanto, cuidado ao armazenar saídas maiores, para não estourar a memória disponível.
E aí, alguém tem mais alguma idéia? Essas funções são realmente bem úteis, acredito que com o tempo virão surgindo novas aplicações para elas, se pintar mais alguma idéia interessante, manda pra gente... Para mais informações, consulte o Manual. Mesmo que você não venha utilizar isso agora, é importante conhecer. Creio que todo programador deve ter pelo menos duas máximas para novos desafios: 1 - "Não sei mas posso aprender", 2 - "Não sei tudo, mas sei onde procurar", e é lendo que se aprende onde procurar, pelo menos é uma das principais fontes... :) Outra coisa: apesar de eu estar ensinando a fazer aqui algumas "adaptações", procure buscar sempre a melhor maneira de fazer o que precisa ser feito, fazer bem feito para não ter que fazer de novo, e não usar emendas demais... Seja organizado! Espero ter deixado claro os exemplos... Caso tenham alguma dúvida é só falar; dúvidas, críticas e sugestões são bem-vindas.
No demais, busquem, pesquisem, se aperfeiçoem, estudem, passeiem pelos manuais, troquem idéia, aprendam novas tecnologias e novas técnicas! Seja um desenvolvedor, e não "o carinha que faz site e o banco de dados".
Um abraço, vida longa e próspera, e até a próxima! :)