Tratamento de Erros em PHP: das construções básicas aos padrões profissionais
Qualquer desenvolvedor PHP, mais cedo ou mais tarde, enfrenta situações em que o código não se comporta como esperado. Arquivo não encontrado, banco de dados indisponível, usuário inseriu dados inválidos — tudo isso são situações excepcionais. Um tratamento de erros competente transforma uma aplicação frágil em um sistema confiável. Neste artigo, abordaremos todos os aspectos do trabalho com erros em PHP: desde o simples try/catch até a criação de classes de exceção personalizadas e manipuladores globais.
1. Fundamentos: a construção try/catch e throw
Em PHP, exceções são objetos da classe Exception (ou de suas subclasses). O mecanismo básico consiste em três palavras-chave:
try— bloco onde o código potencialmente perigoso é executado;catch— bloco que captura a exceção;throw— operador que "lança" a exceção.
Vejamos um exemplo simples:
<?phpfunction divide($a, $b) { if ($b == 0) { throw new Exception('Divisão por zero impossível'); } return $a / $b;}
try { echo divide(10, 0);} catch (Exception $e) { echo 'Erro: ' . $e->getMessage();}?>Quando a execução atinge o throw, o PHP sai imediatamente da função atual e procura um bloco catch adequado. Se um catch for encontrado, a execução continua a partir dele. Caso contrário, ocorre um erro fatal.
Importante: a partir do PHP 7, a maioria dos erros internos (como divisão por zero) passou a lançar exceções da classe DivisionByZeroError. Para capturá-los, é necessário especificar o tipo correspondente.
2. Recursos avançados: múltiplos catch e finally
Frequentemente, em um único bloco try, podem ocorrer diferentes tipos de exceções. O PHP permite criar vários blocos catch para classes diferentes:
<?phpclass ValidationException extends Exception {}class DatabaseException extends Exception {}
try { // código que pode lançar diferentes exceções} catch (ValidationException $e) { echo 'Erro de validação: ' . $e->getMessage();} catch (DatabaseException $e) { echo 'Erro de banco de dados: ' . $e->getMessage();} catch (Exception $e) { // Manipulador geral para todas as outras exceções echo 'Erro desconhecido: ' . $e->getMessage();}?>A ordem dos blocos catch é importante: o PHP os verifica sequencialmente, e o primeiro que corresponder ao tipo captura a exceção. Portanto, o catch (Exception $e) geralmente é colocado por último.
O bloco finally é executado em qualquer caso — tanto após a conclusão bem-sucedida do try, quanto após a captura da exceção, e mesmo se houver um operador return no catch. É o local ideal para fechar arquivos, liberar recursos ou registrar no log:
<?phpfunction readConfig($filename) { $handle = fopen($filename, 'r'); if (!$handle) { throw new Exception('Não foi possível abrir o arquivo'); } try { // leitura dos dados return fread($handle, filesize($filename)); } finally { fclose($handle); // o arquivo será fechado mesmo com exceção }}?>3. Classes de exceção personalizadas e manipuladores globais
Criar suas próprias classes de exceção é uma ferramenta poderosa para estruturar o código. Basta herdar de Exception:
<?phpclass InvalidEmailException extends Exception { public function __construct($email, $code = 0, Throwable $previous = null) { $message = "Email '$email' possui formato inválido"; parent::__construct($message, $code, $previous); }}
function validateEmail($ema