ignore_user_abort()
Neste artigo, focamos na função PHP ignore_user_abort(): o que ela faz, sua sintaxe, como funciona com connection_aborted() e exemplos práticos.
A função PHP ignore_user_abort() controla se um script continua sendo executado após a desconexão do cliente (o navegador do usuário). Esta página aborda o que a função faz, sua assinatura e valor de retorno, como ela funciona em conjunto com connection_aborted(), as armadilhas mais comuns e um exemplo completo de tarefa em segundo plano.
O que ignore_user_abort() faz
Quando um usuário fecha a aba do navegador, clica em Parar ou navega para outra página, a conexão com o servidor é encerrada. Por padrão, o PHP não interrompe o script no instante em que isso acontece — ele só percebe a conexão inativa na próxima vez que tenta enviar dados ao navegador, momento em que encerra o script. A função ignore_user_abort() muda esse comportamento: com ela ativada, o PHP continua executando o script até o final, mesmo que ninguém esteja mais ouvindo.
Isso é importante para operações que não podem ser deixadas pela metade — gravar no banco de dados, processar um pagamento, enviar um e-mail ou gerar um relatório. Se o usuário se desconectar no meio do processo, geralmente é preferível que o trabalho seja concluído a deixar o sistema em um estado inconsistente.
Um "abort de cliente" é um evento de nível de transporte: o PHP só o detecta quando tenta escrever em uma conexão que já está fechada. Por isso o tempo de detecção parece indireto — veja Por que o abort é detectado tarde abaixo.
Sintaxe
ignore_user_abort(?bool $enable = null): int$enable— passetruepara ignorar desconexões do cliente, oufalsepara restaurar o comportamento padrão (abortar na desconexão). Se o argumento for omitido, a configuração atual é mantida e apenas retornada.- Valor de retorno — a configuração anterior como um inteiro (
1= estava ignorando aborts,0= não estava). Isso permite salvar e restaurar o estado.
<?php
$previous = ignore_user_abort(true); // turn it on, remember old value
// ... critical work ...
ignore_user_abort($previous); // restore whatever it was beforeA mesma configuração pode ser definida globalmente no php.ini com a diretiva ignore_user_abort; chamar a função substitui essa configuração para a requisição atual.
Uso básico
Chame a função uma vez próximo ao início do trabalho que você deseja proteger:
<?php
// Keep running even if the user disconnects.
ignore_user_abort(true);
// Critical code that must not be interrupted.
saveOrderToDatabase();
chargePayment();
sendConfirmationEmail();
// Optional: go back to the default behaviour.
ignore_user_abort(false);Note que ignore_user_abort() mantém o script ativo, mas não remove o limite de max_execution_time do PHP. Uma tarefa de longa duração ainda pode ser encerrada pelo limite de tempo, por isso combine-a com set_time_limit() quando necessário.
Detectando o abort com connection_aborted()
Ignorar um abort não significa que você não pode reagir a ele. A função connection_aborted() retorna 1 após o cliente se desconectar e 0 caso contrário, permitindo verificá-la dentro de um loop e decidir se continua, faz a limpeza e encerra.
Uma sutileza: o PHP só atualiza o status da conexão quando tenta enviar dados e o buffer é liberado. Portanto, para detectar um abort no meio de um loop, normalmente usa-se echo e flush(), o que força o PHP a perceber o socket encerrado.
<?php
ignore_user_abort(true);
for ($i = 0; $i < 10; $i++) {
// Push some output so PHP checks the connection state.
echo "Step $i\n";
flush();
// connection_aborted() returns 1 after the client disconnects.
if (connection_aborted()) {
// The user left — stop early and clean up if we want to.
break;
}
doExpensiveStep($i);
}
ignore_user_abort(false);Aqui connection_aborted() permite que o script decida por si mesmo: pode terminar silenciosamente, registrar que o usuário saiu ou interromper cedo. Relacionado: connection_status() relata os três estados (normal, abortado, tempo esgotado) como um bitmask.
Um exemplo prático de tarefa em segundo plano
Um padrão comum é enviar a resposta, fechar a conexão para que o navegador pare de aguardar e, em seguida, continuar o trabalho pesado em segundo plano. É o ignore_user_abort(true) que faz a parte de "continuar" funcionar.
<?php
// 1. Keep running after the browser is released.
ignore_user_abort(true);
set_time_limit(0); // no execution-time cap for the background work
// 2. Send the response and flush the output buffers.
ob_start();
echo "Thanks! Your request is being processed.";
$size = ob_get_length();
header("Content-Length: $size");
header("Connection: close");
ob_end_flush();
flush();
if (function_exists('fastcgi_finish_request')) {
fastcgi_finish_request(); // PHP-FPM: detach from the client now
}
// 3. The user's browser is already done. This runs regardless.
processLargeReport();O navegador recebe uma resposta rápida e para de girar, enquanto o servidor conclui o trabalho demorado. Sem ignore_user_abort(true), esse trabalho em segundo plano seria encerrado no momento em que o PHP percebesse a conexão fechada.
Por que o abort é detectado tarde
O PHP armazena a saída em buffer. Enquanto esse buffer não é liberado para o cliente, o PHP não tem motivo para tocar o socket e, portanto, nunca descobre que ele está fechado. É por isso que scripts que não produzem saída (ou cuja saída permanece no buffer) podem ser executados até a conclusão após uma desconexão sem nunca relatar connection_aborted() === 1. Se você precisa de detecção oportuna de abort, emita um pequeno heartbeat e libere-o com flush() periodicamente, como no loop acima. Os helpers de buffer de saída ob_flush() e ob_end_flush() oferecem um controle mais fino sobre quando os dados saem do buffer.
Armadilhas comuns
- Não substitui o limite de tempo. Use
set_time_limit(0)(ou um valor generoso) junto com ela para tarefas longas. - A detecção requer saída + flush.
connection_aborted()não mudará para1por conta própria se o script nunca escrever para o cliente. - Um script descontrolado fica mais difícil de parar. Com os aborts ignorados, um loop infinito com bug continua consumindo recursos porque o usuário não pode mais cancelá-lo. Sempre combine com limites sensatos.
- Scripts CLI não são afetados. Não há conexão de cliente na linha de comando, então a função é um no-op lá — use-a em contextos web (de requisição).
Conclusão
ignore_user_abort() mantém um script PHP em execução após a desconexão do cliente, o que é essencial para concluir com segurança trabalhos críticos ou em segundo plano. Combine-a com connection_aborted() para detectar desconexões, flush() para forçar essa detecção, e set_time_limit() para evitar ser interrompido no meio de uma tarefa — e você terá um padrão confiável para trabalhos que não podem ser deixados pela metade.