Entendendo pra que serve ob_start(), ob_end_flush(), ob_get_contents() e afins

Fluxo de dados

Entendendo pra que serve ob_start(), ob_end_flush(), ob_get_contents() e afins

Prefácio

Se você mexe com PHP há um certo tempo, com certeza já deve ter visto em algum lugar estas funções e talvez tenha se perguntando para que elas servem.

A primeira vista pode parecer algo extremamente complexo e avançado, mas a resposta é mais simples do que se imagina.

Conceito

Em primeiro lugar, creio que é importante saber que OB significa Output Buffer. Isso, nada mais é do que o Buffer de saída. Buffer á uma região da memória onde os dados ficam armazenados temporariamente até que sejam despejados para a aplicação. Nesse caso, o buffer seria a saída pro navegador.

E qual a utilidade disso?

Você já deve ter se deparado com algum erro que dizia Headers already sent. Isso se dá porque já foi enviada alguma saída para o navegador. Cabeçalhos só podem ser enviados antes de qualquer saída html.

Um ob_start() irá pegar todos os dados de saída e guardar em buffer. Os dados só serão enviados ao navegador no momento em que você encerrar o buffer.

Existem três meios de encerrar o flush:

1. ob_end_flush(): Envia o conteúdo do buffer para a saída, esvazia-o e encerra o buffering;
2. ob_flush(): Envia o valor do buffer para o navegador e esvazia-o. Todas as entradas a seguir continuam indo para o buffer;
3. ob_end_clean(): Esvazia o buffer e encerra-o. Nenhuma saída é enviada.

Adicionalmente você pode utilizar a função ob_clean(), que apenas limpa o buffer.

Outra função que é muito importante é a ob_get_contents(), que irá retornar o conteúdo do buffer.

A seguir, veremos um exemplo simples de como guardar o retorno do phpinfo() dentro de um arquivo, utilizando o buffer para não enviar a saída para o navegador.

Mão na massa

Em primeiro lugar devemos iniciar o buffer. Depois iremos prosseguir como se fossemos executar o phpinfo() normalmente, porém a saída será guardada no buffer ao ivés de jogada na tela. Em seguida pegamos o resultado do buffer e gravamos em um arquivo HTML.

// Inicializa o buffer e bloqueia qualquer saída para o navegador
ob_start();

// Executamos o phpinfo() normalmente
phpinfo();

// Neste momento nenhuma saída foi enviada ao navegador

// Recebemos o valor do buffer na variável $resultado
$resultado = ob_get_contents();

// Já podemos encerrar o buffer e limpar tudo que há nele
ob_end_clean();

// Agora é só gravar um arquivo com os dados coletados
$ok = file_put_contents('phpinfo.html', $resultado);

// Envia uma mensagem para o usuário indicando se ocorreu tudo OK
if ($ok) {
    print 'Arquivo gravado com sucesso.<br>';
    print '<a href="phpinfo.html">Clique aqui para visualizar</a>';
} else {
    print 'Ocorreu um erro. Verifique as permissões.';
}

Conclusão

Trabalhar com buffer é ter milhões de possibilidades nas mãos. Você pode encontrar diversas utilidades para o seu uso. Eu gostaria muito que vocês comentasses sobre suas experiências utilizando estas técnicas.

Lembrando sempre: toda sugetão para novas colunas são sempre bem vindas!

Um abraço a todos e fiquem com Deus!
Rafael Jaques

  • Legal, não conhecia essas funções.

    Bom saber que elas existem, e que podem ser úteis :D

    Valeu por explicar ;)

    Abraço.

  • Rafael, trabalhar com as funções de buffer não seria a mesa coisa que trabalhar com $_session????

    Alguns dia atrás tive um problema, pois para algumas paginas do meu site vinha um erro antes do start_session();, depois de pesquisar muito, descobri que a codificação do meu documento php não tinha o formato padrão, as funções decritas acima resolveriam o meu problema??

  • Cara, esse OB_start me deu uma baile tempos atrás. Desenvolvi um sistema que rodava perfeitamente localmente em qualquer navegador, e online rodav apenas no firefox, sendo que problema diagnosticado foi que o Internet Explorer(qualquer versão) não estava conseguindo resgatar os dados gravados na sessão, parecia q simplesmente a sessão morria. A solução foi bufferizar todo conteúdo logo após iniciar a sessão, e mandar um cabelho from hell pro IE manter o buffer em cache, segue o famigerado código de iníco das páginas do sistema:

    <?php

    header('P3P: CP="CAO PSA OUR"');

    ob_start();

    //Resto do sistema

    ?>

    Certas coisas somente a microsoft entende mesmo…

  • Faltou o principal, se algúem por aew pegar um problema do IE não consguir gravar nem ler na sessão, coloca akele código logo após iniciar a sessão que não tem erro, problema resolvido!

  • Humberto

    Uma outra utilizadade destas funções é na criação de templates, onde vc teria um arquivo com o conteudo e algum padrão que seria substituido por um conteudo dinamico.

  • Squik..

    Na verdade uma coisa não tem a ver com a outra…

    A session vai trabalhar com as variáveis de sessão da tua aplicação..

    E estas funções trabalham com o buffer.. O buffer é apenas a saída pro navegador..

    É claro que, usando buffer, você pode neutralizar alguns bugs de sessão, quando você envia saidas indesejadas ao navegador..

    Mas não sei se vai resolver o seu problema..

    Abraço!

  • Vinícius

    Gostei do Post. Muito informativo. Continuem por favor, mal posso esperar pelo próximo.

  • Denis Lins

    Te amo cara! kkk

    Me ajudou muito isso, achei meio sem quere este post mas foi de grande ajuda, valeu! :D

  • Não conhecia este site a gostei realmente muito!

    Sigam em frente que, pela qualidade, o site vai bombar!

    Parabéns!!!

  • Juliana

    gostei, estava procurando algo assim para enviar uma imagem gerada no php para um email… agora vamos ver se vai dar certo! obrigada!

  • adrian

    Muito bom!!

    Ainda não conhecia essas funções e realmente são muitas as possibilidades de uso.

    Estou tentando fazer um pequeno sistema de chat e acho que essa é uma função ideal.

  • belo artigo, parabéns.

    aproveitando, uma coisa que pode ser feito utilizando o conjunto de funções apresentadas é um esquema de cache de view. simples e poderoso.

    []

  • Roseane

    Oi Rafael. Eu to com um probleminha acontecendo no meu script e talvez você possa me ajudar. Estou usando a biblioteca FPDF para gerar relatórios online. Só que quando há muita informação no relatório (imprime um retorno de sql grande), da o seguinte erro "Fatal error: Allowed memory size of…". O FPDF armazena os dados em buffer antes de imprimir. Só que nos meus testes descobri que o buffer não está sendo limpo a cada requisição. Meu php está configurado com 16M de memória. Para testar, fui aumentando gradativamente para 17M, 18M, 19M, 20M… em todos esses casos o erro persistiu. Então aumentei para 30M e consegui imprimir o relatório sem erros. Mas como o relatório está em desenvolvimento ainda, fui imprimindo várias vezes (gerando várias requisições) até que o erro apareceu de novo, dizendo que 30M já não eram mais suficientes. Tentei usar a função ob_clean() mas apresenta o seguinte notice "Notice: ob_clean() [ref.outcontrol]: failed to delete buffer. No buffer to delete. ". Eu poderia colocar um ini_set() com um valor bem grande para a memória, mas como esse script vai ficar no servidor e várias pessoas poderão imprimir o relatório pode ser que em algum momento esse erro ocorrerá. Você tem alguma idéia que possa me ajudar?

    Roseane

    • adriano avelino

      Estou com um problema semelhante, caso tenha obtido sucesso favor compartilhar. Abraço!

  • Luccas

    Cara bom dia!
    Eu não sei quase nada sobre php, mais o pouco que sei me fez ter vontade de ingressar na carreira. Gostaria que você pudesse me ajudar em relação a escolha de curso pois estava querendo fazer na Impacta mais não sei como funciona e se talvez eu conseguiria acompanhar o rítimo do curso em si.

    Valeu desde já!

    Abç,
    Luccas

  • Muito bom…. Esse material me auxiliou na resolução de um problema no sistema que estou desenvolvendo!

    Surgia o erro quando eu usava um cabeçalho HTML na página e contia um header logo abaixo…. Obrigado!

  • belo post

  • O Firefox detectou que o pedido para este endereço não será concluído devido à forma que o servidor o está redirecionando.

    Este problema algumas vezes pode ser causado pela desativação ou bloqueio de cookies.

    Acesso a área administrativa do meu site em joomla versão 2.5.16 a mais atual , porém quando tento acessar o site recebo a mensagem acima, o provedor é locaweb , os analistas dizem que está tudo ok , porém o meu output_buffering está 4096 , faço a mudança para off porém o php não aceita….. meus conhecimentos são somente em joomla ,de php sou apenas um curioso que seguindo os tutoriais me viro muita das vezes. Me desculpe a ignorância ,mas quem não pergunta não aprende.
    Abraço a todos

    P.S Ainda estou preparando o site , conto com posts de vocês na sequência.

  • Cicero Joceilton

    Eu conhecia essa função ob_start, mas não sabia muito bem utilizar.

    você me ajudou muito

  • Muito bom esse artigo! se você ainda quiser pode até implementar essa técnica para gerar arquivos pdf na saída do Buffer. Parabéns.

  • Marcio Nonato

    Cara! isso foi uma mão na roda. Resolvi o meu problema com um erro do tipo: Warning: Cannot modify header information – headers already sent by…”

  • marlonla

    Muito bem explicado!!

    Obrigado! Jah bless!

  • Muito obrigado. Otima explicação.

  • Marcos

    Utilizo o buffer para fazer a compactação da saida do HTML/PHP a fim de melhorar o desempenho.

  • Elio Laender

    Excelente explicação. obrigado!

  • Oi, pessoal estou tentando instalar o php-nuke versão 8.3.2 mas ta dando esse erro como consertar? isso está acontecendo no host local, desde já muito grato por sua atenção. Segue os erros: Warning: ob_start(): second array member is not a valid method in C:wampwwwhtmlmainfile.php on line 86

    Call Stack

    # Time Memory Function Location

    1 0.0430 152904 {main}( ) ..index.php:0

    2 0.0910 523840 require_once( ‘C:wampwwwhtmlmainfile.php’ ) ..index.php:14

    3 0.0910 524816 ob_start ( ) ..mainfile.php:86

    ( ! ) Notice: ob_start(): failed to create buffer in C:wampwwwhtmlmainfile.php on line 86

    Call Stack

    # Time Memory Function Location

    1 0.0430 152904 {main}( ) ..index.php:0

    2 0.0910 523840 require_once( ‘C:wampwwwhtmlmainfile.php’ ) ..index.php:14

    3 0.0910 524816 ob_start ( ) ..mainfile.php:86

    ( ! ) Deprecated: Function ereg() is deprecated in C:wampwwwhtmlmainfile.php on line 88

    Call Stack

    # Time Memory Function Location

    1 0.0430 152904 {main}( ) ..index.php:0

    2 0.0910 523840 require_once( ‘C:wampwwwhtmlmainfile.php’ ) ..index.php:14

  • Augusto Paiva

    Muito bom, Rafael!

    Já usei o ob_clean quando precisei receber um json de uma requisição post, mas o formato não era reconhecido pois no buffer estava sendo enviado junto um caractere especial invisível. Bastou limpar o buffer antes de retornar o json e voilat!

    Um Abraço!

  • Márcio Vennan

    Muito bom o post! Isso vai me ajudar muito. Obrigado!

  • João Assef

    Muito bom!

  • Sandro Griebeler

    Muito bom. Obrigado.

  • Francisco Prado Rodrigues

    2017 e seu artigo me serviu de referência! Já tinha estudado a respeito anos atrás, mas precisei revisar e encontrei aqui! Usando para otimizar um tema WordPress, criando cache de determinadas áreas do site e reduzir queries ao banco! :)