Boas Práticas de Tratamento de Erros em PHP

Backend2026-09-25TryQuickToolBox

Você acabou de implantar um novo recurso e, de repente, sua aplicação PHP lança um erro fatal. Os usuários veem uma página em branco e seus logs estão vazios. Parece familiar? O tratamento inadequado de erros é uma das razões mais comuns pelas quais o código PHP se torna insustentável. Neste artigo, vamos percorrer práticas práticas de tratamento de erros em PHP que tornarão seu código mais robusto, mais fácil de depurar e mais simples de manter.

Por que o Tratamento de Erros em PHP Importa

O PHP é tolerante por padrão: muitas vezes continua a execução após um aviso, e erros podem ser silenciosamente ignorados. Essa flexibilidade é uma faca de dois gumes. Sem o tratamento adequado, os erros podem:

Um bom tratamento de erros garante que, quando algo der errado, você saiba disso, possa corrigi-lo rapidamente e seus usuários tenham uma experiência agradável.

1. Defina Níveis de Relatório de Erros Apropriados

O primeiro passo é configurar corretamente o relatório de erros do PHP para o seu ambiente. Em desenvolvimento, você quer ver todos os erros; em produção, você quer registrá-los, mas não exibi-los.

// Desenvolvimento
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// Produção
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/php-error.log');
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);

Use variáveis de ambiente ou arquivos de configuração para alternar entre essas configurações automaticamente. Nunca dependa de editar manualmente o php.ini em servidores de produção.

2. Use Exceções em Vez de Códigos de Erro

Retornar códigos de erro (como false ou -1) é um padrão legado que polui seu código e facilita ignorar falhas. As exceções forçam você a lidar com erros explicitamente e mantêm seu caminho feliz limpo.

// Ruim: código de erro
function getUser($id) {
    $user = db_find($id);
    if (!$user) {
        return false; // o chamador deve verificar
    }
    return $user;
}

// Bom: exceção
function getUser($id) {
    $user = db_find($id);
    if (!$user) {
        throw new UserNotFoundException("Usuário $id não encontrado");
    }
    return $user;
}

Crie classes de exceção personalizadas para diferentes tipos de erro. Isso facilita capturar erros específicos e tratá-los adequadamente.

3. Capture Exceções no Nível Certo

Um erro comum é capturar exceções cedo demais ou de forma muito ampla. Capture exceções apenas quando você puder realmente fazer algo a respeito—registrá-las, tentar novamente ou mostrar uma mensagem amigável ao usuário.

try {
    $user = getUser($id);
    $order = createOrder($user, $items);
} catch (UserNotFoundException $e) {
    // Tratar usuário ausente especificamente
    return response('Usuário não encontrado', 404);
} catch (PaymentFailedException $e) {
    // Tratar falha de pagamento
    return response('Pagamento falhou: ' . $e->getMessage(), 400);
} catch (Throwable $e) {
    // Captura geral para erros inesperados
    log_error($e);
    return response('Algo deu errado', 500);
}

Use Throwable (PHP 7+) para capturar tanto exceções quanto erros. Evite blocos catch vazios—se você capturar, faça algo significativo.

4. Registre Erros com Contexto

O logging é seu melhor amigo para depurar problemas de produção. Mas uma mensagem de log como "Ocorreu um erro" é inútil. Inclua contexto: ID do usuário, parâmetros da requisição, stack trace e timestamps.

try {
    processPayment($order);
} catch (PaymentException $e) {
    error_log(sprintf(
        "Pagamento falhou para pedido %d: %s em %s:%d\nStack trace: %s",
        $order->id,
        $e->getMessage(),
        $e->getFile(),
        $e->getLine(),
        $e->getTraceAsString()
    ));
    throw $e; // relançar após registrar
}

Considere usar uma biblioteca de logging como Monolog para logs estruturados. Ela suporta diferentes handlers (arquivo, syslog, Slack) e níveis de log (debug, info, warning, error).

5. Crie um Handler de Erros Personalizado

O handler de erros padrão do PHP imprime erros na tela, o que não é adequado para produção. Um handler de erros personalizado permite converter erros em exceções, registrá-los ou exibir uma página de erro amigável.

set_error_handler(function ($severity, $message, $file, $line) {
    if (!(error_reporting() & $severity)) {
        return false; // respeitar as configurações de error_reporting
    }
    throw new ErrorException($message, 0, $severity, $file, $line);
});

set_exception_handler(function ($e) {
    log_error($e);
    http_response_code(500);
    include 'views/error.php';
});

register_shutdown_function(function () {
    $error = error_get_last();
    if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        log_error(new ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']));
    }
});

Essa configuração garante que todos os erros—incluindo os fatais—sejam registrados e tratados de forma agradável.

6. Valide a Entrada e Falhe Cedo

Muitos erros derivam de entrada inválida. Valide os dados nos limites da sua aplicação (controllers, endpoints de API) e lance exceções imediatamente se a validação falhar. Isso evita que erros se propaguem para dentro do seu código.

function createUser(array $data) {
    if (empty($data['email'])) {
        throw new InvalidArgumentException('Email é obrigatório');
    }
    if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
        throw new InvalidArgumentException('Formato de email inválido');
    }
    // ... prosseguir com confiança
}

Use as funções de filtro do PHP ou uma biblioteca de validação (como Respect\Validation) para manter a validação consistente.

7. Não Suprima Erros com @

O operador @ silencia erros, tornando a depuração mais difícil. É tentador usá-lo ao chamar funções que podem emitir avisos (como file_get_contents), mas ele esconde problemas reais. Em vez disso, verifique pré-condições ou use try-catch com exceções.

// Ruim
$content = @file_get_contents($url);

// Bom
if (!is_readable($url)) {
    throw new RuntimeException("Não é possível ler $url");
}
$content = file_get_contents($url);

Se você precisar suprimir, faça isso apenas para casos bem compreendidos e documente o motivo.

8. Use um Middleware Centralizado de Tratamento de Erros

Em frameworks como Laravel ou Symfony, o tratamento de erros geralmente é centralizado em middleware ou em um handler de exceções. Se você estiver construindo o seu próprio, crie um ponto de entrada único que capture todas as exceções e as converta em respostas HTTP.

// No seu front controller (index.php)
try {
    $response = $router->dispatch($request);
} catch (HttpException $e) {
    $response = new Response($e->getMessage(), $e->getStatusCode());
} catch (Throwable $e) {
    log_error($e);
    $response = new Response('Erro Interno do Servidor', 500);
}
$response->send();

Isso mantém a lógica de tratamento de erros em um só lugar e garante consistência.

Comparação: Abordagens de Tratamento de Erros

Abordagem Prós Contras
Códigos de erro Simples, sem exceções Fácil de ignorar, polui o código
Exceções Força o tratamento, separação limpa Pode ser usado em excesso, sobrecarga de desempenho
Handler de erros personalizado Centralizado, captura todos os erros Requer configuração, pode mascarar erros se mal configurado
Apenas logging Não intrusivo, bom para monitoramento Não trata erros, apenas registra

FAQ

Qual é a diferença entre erros e exceções em PHP?

Erros são problemas de baixo nível, como erros de sintaxe ou de tipo, enquanto exceções são objetos lançados que representam condições excepcionais. No PHP 7+, ambos implementam a interface Throwable, então você pode capturar ambos com um único bloco catch.

Devo usar try-catch para cada chamada de função?

Não, isso leva a um código excessivamente defensivo. Capture exceções apenas quando puder tratá-las de forma significativa—registrar, tentar novamente ou mostrar uma mensagem amigável ao usuário. Deixe as exceções borbulharem até um handler central para casos inesperados.

Como faço para registrar erros sem expor dados sensíveis?

Sanitize as mensagens de log removendo senhas, tokens e dados pessoais. Use logging estruturado com campos de contexto e configure sua biblioteca de logging para redigir chaves sensíveis. Além disso, garanta que os arquivos de log sejam armazenados com segurança e o acesso seja restrito.

Pronto para simplificar seu tratamento de erros em PHP? Comece auditando suas configurações atuais de relatório de erros e implementando um handler de erros personalizado. Para depuração rápida de payloads JSON ou logs, experimente nosso JSON Formatter para validar e formatar seus dados.