Tratamento de Erros em PHP: try/catch e muito mais
O tratamento de erros é uma das tarefas principais de qualquer desenvolvedor web. Um código PHP bem escrito não apenas executa a lógica de negócios, mas também reage corretamente a situações imprevistas: arquivo ausente, problemas com banco de dados, entrada de dados inválida pelo usuário. Neste artigo, vamos detalhar como funciona o tratamento de erros em PHP, começando com o básico try/catch e terminando com técnicas avançadas — exceções personalizadas e manipuladores globais.
1. Fundamentos: a estrutura try/catch
A forma mais comum de tratar erros no PHP moderno é a estrutura try/catch. Ela permite "capturar" uma exceção (objeto da classe Throwable ou seus descendentes) e executar um código alternativo em vez da interrupção abrupta do script.
A sintaxe básica é a seguinte:
<?phptry { // Código que pode lançar uma exceção $file = fopen('data.txt', 'r'); if (!$file) { throw new Exception('Não foi possível abrir o arquivo'); } // Trabalhando com o arquivo...} catch (Exception $e) { // Tratamento do erro echo 'Ocorreu um erro: ' . $e->getMessage();}?>No bloco try, coloca-se o código potencialmente perigoso. Se dentro dele ocorrer uma exceção (através de throw ou devido a um erro interno do PHP), a execução é imediatamente transferida para o bloco catch. A variável $e contém o objeto da exceção, no qual podemos chamar métodos:
getMessage()— texto do erro;getCode()— código numérico do erro;getFile()— arquivo onde ocorreu o erro;getLine()— linha que causou o erro.
2. Bloco finally: código que é executado sempre
Às vezes, é necessário executar certas ações independentemente de ter ocorrido um erro ou não — por exemplo, fechar uma conexão com o banco de dados ou liberar recursos. Para isso, usamos o bloco finally:
<?phpfunction processData($data) { try { // Operação perigosa if (empty($data)) { throw new InvalidArgumentException('Os dados não podem estar vazios'); } echo "Processando dados..."; return true; } catch (InvalidArgumentException $e) { echo "Erro: " . $e->getMessage() . ""; return false; } finally { echo "O bloco finally é executado sempre."; }}
processData([]); // Exibe: Erro: Os dados não podem estar vazios, depois o bloco finallyprocessData('test'); // Exibe: Processando dados..., depois o bloco finally?>O bloco finally é executado mesmo se houver um operador return no try ou no catch. Isso garante a limpeza dos recursos.
3. Exceções personalizadas: estendendo a classe Exception
Em projetos reais, raramente nos limitamos à classe padrão Exception. É muito mais conveniente criar nossas próprias classes de exceção para diferentes tipos de erros. Isso torna o código mais legível e facilita a captura de situações específicas.
Exemplo: vamos criar uma exceção para erros de validação e outra para erros de banco de dados.
<?phpclass ValidationException extends Exception {}class DatabaseException extends Exception {}
function validateUser($age) { if ($age < 0 || $age > 150) { throw new ValidationException('Idade inválida'); } return true;}
function connectToDatabase($dsn) { if (empty($dsn)) { throw new DatabaseException('DSN não pode estar vazio'); } // Simulação de conexão...}
try { validateUser(200);} catch (ValidationException $e) { echo 'Erro de validação: ' . $e->getMessage();}
try { connectToDatabase('');} catch (DatabaseException $e) {