Quando o flush() é mais importante do que parece

O output buffering do PHP é uma daquelas coisas que ninguém percebe — até o dia em que ela destrói o comportamento do seu sistema em produção.

No meu caso, era um dashboard com rotas amigáveis e múltiplos filtros. O fluxo funcionava perfeitamente quando o filtro de cliente ficava vazio, mas bastava escolher “all” e tudo travava.
Nenhum erro de lógica, nada no log, apenas um carregamento eterno e o navegador parado.

O sintoma era estranho: o HTML principal renderizava, mas o JavaScript, responsável por reconstruir a URL e atualizar os gráficos, simplesmente não rodava. Quando o display_errors estava ativo, tudo voltava a funcionar — o que é o tipo de coisa que nenhum desenvolvedor quer admitir.

O problema estava no timing.
O PHP, por padrão, mantém o buffer de saída aberto até o final do script.
Isso significa que o navegador não recebe o HTML imediatamente, e alguns scripts podem tentar interagir com elementos que ainda não chegaram.
Se o fluxo de saída estiver comprimido, empacotado por mod_deflate ou output_buffering, o atraso pode ser ainda maior.

A correção foi simples, (mas não significa que foi rápida e pacífica =/) e contraintuitiva: forçar o envio do conteúdo no ponto exato em que o PHP termina a renderização do cabeçalho da página, antes do JavaScript que depende desse conteúdo.

$clienteGet = trim((string)(get(5) ?? ''));
$clienteGet = $clienteGet === '' ? 'all' : $clienteGet;

// --- NÃO MEXER ---
// Mantém o sistema vivo e sincronizado com o navegador.
// O flush força o envio imediato do HTML parcial antes dos scripts JS rodarem.
// Sem isso, o buffer do PHP atrasa a renderização e quebra os filtros/URLs.
// Repita comigo: NÃO MEXER NESSE TRECHO.

if (ob_get_level() > 0) {
    @ob_flush();
}
@flush();

Essas duas linhas instruem o PHP a esvaziar o buffer atual e enviar os dados imediatamente ao cliente HTTP.
Em sistemas que misturam renderização de servidor e execução de scripts assíncronos, isso evita que o navegador fique “esperando o resto da página” antes de processar eventos, redirecionamentos ou requisições AJAX.

Vale lembrar que ob_flush() e flush() não são mágicos:

  • Eles só funcionam se não houver buffering adicional em nível de servidor (ex: Nginx, Apache, FastCGI).
  • E devem ser usados apenas quando o tempo de entrega do HTML interfere na execução do front-end, nunca como remendo genérico.

Mas quando o sintoma é esse — comportamento diferente entre debug ligado e desligado — pode apostar: é o buffer segurando o show.

“Nem todo bug é um erro. Às vezes, é apenas o PHP sendo educado demais pra enviar o que você pediu.”

Rolar para cima