Para mostrar os erros do PHP, coloque estas linhas no topo do script: ini_set('display_errors', '1'); e error_reporting(E_ALL);. A primeira faz o PHP imprimir mensagens de erro, a segunda faz ele relatar todos os tipos de erro, incluindo avisos e depreciações.
<?php
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
Com isso no lugar, um erro como ler uma variável que nunca foi definida imprime uma mensagem com o arquivo e o número da linha, em vez de falhar em silêncio:
Warning: Undefined variable $total in /home/index.php on line 7
error_reporting() chamado sem argumento retorna a configuração atual como número. Clique em Run para definir um nível e decodificá-lo de volta em nomes:
Cada tipo de erro é um bit, então E_ALL & ~E_DEPRECATED significa "tudo menos depreciações". Mude a primeira linha para error_reporting(E_ERROR | E_WARNING); e rode de novo.
Exibir erros no php.ini
Uma configuração no script só vale depois que o script começa a rodar. Para mostrar erros em todos os scripts, incluindo erros de sintaxe, altere o php.ini (encontre-o com php --ini):
; Development
display_errors = On
display_startup_errors = On
error_reporting = E_ALL
Reinicie o Apache ou o PHP-FPM depois de editar. O servidor embutido php -S e a linha de comando leem o arquivo a cada inicialização. Em hospedagem compartilhada sem acesso ao php.ini, o Apache com mod_php também aceita linhas no .htaccess:
php_flag display_errors on
php_value error_reporting -1
-1 liga todos os bits, o que equivale a E_ALL.
Os níveis de erro
| Constante | O que dispara | Para o script |
|---|---|---|
E_ERROR | Erro fatal em tempo de execução, como falta de memória | sim |
E_PARSE | Erro de sintaxe no arquivo | sim |
E_WARNING | Variável ou chave de array indefinida, arquivo ausente num include | não |
E_NOTICE | Problemas menores (poucos restam no PHP 8) | não |
E_DEPRECATED | Código que uma versão futura do PHP vai rejeitar | não |
E_USER_* | Erros que você dispara com trigger_error() | só E_USER_ERROR |
E_ALL | Todos os níveis, incluindo erros de núcleo e de compilação não listados aqui |
O PHP 8.0 transformou muitos avisos antigos em exceções: dividir por zero com / e passar o tipo errado para uma função nativa agora lançam uma subclasse de Error, do mesmo jeito que chamar uma função indefinida faz desde o PHP 7. Você pode capturar os três:
Exceções são explicadas em try e catch. Avisos, notices e depreciações continuam passando pelo sistema de relatório de erros descrito aqui.
Registrar erros em log em vez de exibi-los
Num site no ar, os visitantes nunca devem ver mensagens de erro: elas revelam caminhos, SQL e código. Escreva-as num arquivo de log:
; Production
display_errors = Off
log_errors = On
error_log = /var/log/php/app-errors.log
error_reporting = E_ALL
Mantenha error_reporting = E_ALL em produção. Reduzir esse valor não faz os erros sumirem, só impede que você fique sabendo deles. Suas próprias mensagens podem ir para o mesmo log com error_log():
<?php
error_log("Payment failed for order 1042");
Depois acompanhe o arquivo enquanto testa: tail -f /var/log/php/app-errors.log.
Transformar avisos em exceções com set_error_handler
set_error_handler troca o tratamento padrão do PHP para avisos, notices e depreciações por uma função sua. Um padrão comum converte cada um deles numa ErrorException, então uma chave de array esquecida para o código como qualquer outra exceção e pode ser capturada:
O handler recebe o nível do erro como primeiro argumento, então pode tratar cada nível de um jeito. Este só registra depreciações em log e transforma todo o resto em exceção:
Erros fatais e erros de sintaxe nunca chegam ao handler, porque o script não consegue continuar depois deles. Para registrá-los, cadastre uma função de shutdown que lê error_get_last().
Ler o último erro com error_get_last
Algumas funções retornam false e informam o motivo só como aviso, por exemplo file_get_contents num arquivo que não existe. error_get_last() retorna esse aviso como array, o que é útil quando você quer mostrar sua própria mensagem:
O operador @ na frente da chamada suprime a mensagem daquela expressão. Use com moderação e só quando você verifica o resultado logo em seguida, como aqui; um @ sozinho só esconde bugs.
Erro comum: os erros estão ligados, mas a página continua em branco
Se você adicionou ini_set('display_errors', '1') e ainda vê uma página branca, o erro provavelmente é de sintaxe. O PHP analisa o arquivo inteiro antes de rodar a primeira linha, então um ; ou } faltando para tudo antes de o ini_set rodar. Verifique o arquivo pelo terminal, que sempre imprime a mensagem:
php -l index.php
Errors parsing index.php
PHP Parse error: syntax error, unexpected token "," in index.php on line 2
O número da linha aponta onde o PHP desistiu, que muitas vezes é a linha depois do erro de verdade. Corrija, rode php -l de novo até aparecer No syntax errors detected e recarregue a página.
Perguntas frequentes
Como exibo todos os erros no PHP?
Adicione ini_set('display_errors', '1'); ini_set('display_startup_errors', '1'); error_reporting(E_ALL); bem no topo do script, ou defina display_errors = On e error_reporting = E_ALL no php.ini e reinicie o servidor web ou o PHP-FPM.
Por que minha página PHP mostra uma tela branca?
Um erro fatal parou o script enquanto display_errors estava desligado, então nada foi impresso. Ative os erros (ou leia o log de erros, por exemplo com tail -f no arquivo para onde error_log aponta) para ver a mensagem e o número da linha.
Por que ini_set('display_errors', 1) não mostra meu erro de sintaxe?
Um erro de sintaxe para o PHP antes de qualquer linha do arquivo rodar, então a chamada a ini_set nunca acontece. Defina display_errors no php.ini, ou coloque o ini_set num arquivo pequeno que depois faz include do arquivo quebrado.
display_errors deve ficar ligado em produção?
Não. Mensagens de erro revelam caminhos de arquivos e detalhes do código aos visitantes. Em produção use display_errors = Off, log_errors = On e um caminho em error_log, e mantenha error_reporting = E_ALL para que os problemas continuem registrados.
O que faz error_reporting(0)?
Desliga o relatório de todos os tipos de erro pelo resto do script, então avisos e até erros fatais não geram mensagem. Isso esconde os problemas em vez de resolvê-los; prefira registrar os erros em log a silenciá-los.