Entendendo Exceções no PHP
Em PHP, exceções são usadas para tratar erros inesperados e problemas em tempo de execução. Aprenda a lançar, capturar e criar exceções personalizadas.
Uma exceção é um objeto que representa um erro ou uma condição inesperada que interrompe o fluxo normal do seu programa. Em vez de retornar um código de erro que o chamador pode esquecer de verificar, o código "lança" uma exceção; o ambiente de execução então desfaz a pilha de chamadas até encontrar um bloco catch correspondente. Se nenhum bloco a capturar, o script é encerrado com um erro fatal.
Este capítulo aborda como lançar e capturar exceções, os métodos que toda exceção expõe (getMessage(), getCode(), getLine(), getFile()), o bloco finally, múltiplos blocos catch, classes de exceção personalizadas e a diferença entre Exception e Error.
O que é uma Exceção PHP?
Uma exceção PHP é um objeto que descende da classe embutida Exception (ou, de forma mais ampla, da interface Throwable). Quando algo dá errado — um arquivo ausente, um argumento inválido, uma conexão de banco de dados com falha — você cria um desses objetos e o throw (lança). Lançar imediatamente interrompe o caminho de execução atual e passa o controle para o manipulador mais próximo.
Use uma exceção quando uma função não puder continuar de forma significativa e o chamador for o lugar certo para decidir o que fazer a seguir. Não as use para fluxo de controle comum (uma busca normal de "usuário não encontrado" é melhor expressa com um valor de retorno).
Lançando uma Exceção
A palavra-chave throw lança uma exceção, seguida de uma nova instância de uma classe de exceção. O construtor aceita uma mensagem opcional, um código inteiro e uma exceção anterior (para encadeamento):
<?php
function divide(int $a, int $b): float
{
if ($b === 0) {
throw new InvalidArgumentException('Division by zero is not allowed.');
}
return $a / $b;
}
try {
echo divide(10, 0);
} catch (InvalidArgumentException $e) {
echo 'Error: ' . $e->getMessage();
}
?>Saída:
Error: Division by zero is not allowed.O código dentro do try é executado normalmente até que throw seja disparado. A partir desse ponto, o restante do bloco try é ignorado e o bloco catch correspondente é executado.
Tratando Exceções com try / catch
Você envolve o código que pode falhar em um bloco try e se recupera da falha em um bloco catch. A variável no catch (aqui $e) contém o objeto de exceção, que expõe vários métodos somente leitura:
| Método | Retorna |
|---|---|
getMessage() | A mensagem legível por humanos |
getCode() | O código inteiro passado ao construtor |
getLine() | A linha onde a exceção foi lançada |
getFile() | O arquivo onde foi lançada |
getPrevious() | A exceção "anterior" encadeada, se houver |
getTraceAsString() | O rastreamento de pilha como string |
<?php
try {
throw new Exception('Something failed', 42);
} catch (Exception $e) {
echo 'Message: ' . $e->getMessage() . PHP_EOL;
echo 'Code: ' . $e->getCode() . PHP_EOL;
}
?>Saída:
Message: Something failed
Code: 42Capturando Múltiplos Tipos de Exceção
Um único bloco try pode ter vários blocos catch. O PHP os verifica de cima para baixo e executa o primeiro cujo tipo corresponda. Desde o PHP 7.1, você também pode capturar vários tipos não relacionados em um único bloco usando o operador pipe (|):
<?php
try {
throw new RuntimeException('Network is down');
} catch (InvalidArgumentException $e) {
echo 'Bad argument: ' . $e->getMessage();
} catch (RuntimeException | LogicException $e) {
echo 'Runtime/logic problem: ' . $e->getMessage();
}
?>Saída:
Runtime/logic problem: Network is downA ordem importa: liste os tipos de exceção mais específicos antes de suas classes pai, caso contrário o catch mais abrangente captura tudo primeiro.
O Bloco finally
O bloco finally é opcional, mas útil. Seu código sempre é executado — independentemente de uma exceção ter sido lançada ou não, e mesmo que o bloco try ou catch execute um return. Isso o torna o lugar certo para limpeza, como fechar um identificador de arquivo ou liberar um bloqueio:
<?php
try {
echo 'Open resource' . PHP_EOL;
throw new Exception('Boom');
} catch (Exception $e) {
echo 'Caught: ' . $e->getMessage() . PHP_EOL;
} finally {
echo 'Cleanup always runs' . PHP_EOL;
}
?>Saída:
Open resource
Caught: Boom
Cleanup always runsClasses de Exceção Personalizadas
Além dos tipos embutidos, você pode definir suas próprias classes de exceção estendendo Exception. Uma classe personalizada permite carregar dados extras (como um valor com falha) e permite que os chamadores capturem seu tipo de erro específico sem capturar acidentalmente outros não relacionados:
<?php
class InsufficientFundsException extends Exception
{
private float $shortfall;
public function __construct(float $shortfall)
{
$this->shortfall = $shortfall;
parent::__construct("Short by $shortfall");
}
public function getShortfall(): float
{
return $this->shortfall;
}
}
try {
throw new InsufficientFundsException(25.5);
} catch (InsufficientFundsException $e) {
echo $e->getMessage() . PHP_EOL;
echo 'Need ' . $e->getShortfall() . ' more.';
}
?>Saída:
Short by 25.5
Need 25.5 more.O PHP também inclui uma família de exceções SPL prontas para uso — InvalidArgumentException, RuntimeException, LengthException, entre outras — portanto, muitas vezes você não precisa criar as suas próprias.
Exception vs. Error
Desde o PHP 7, falhas internas do motor (como um erro de tipo ou chamada de método indefinido) são lançadas como objetos Error, não como objetos Exception. Ambos implementam a interface Throwable. Um simples catch (Exception $e) não capturará um Error. Para tratar ambos, capture a interface:
<?php
try {
$result = 10 % 0; // throws a DivisionByZeroError
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage();
}
?>Saída:
DivisionByZeroError: Modulo by zeroComo regra, reserve Exception para problemas dos quais sua aplicação pode se recuperar, e deixe Error representar bugs que você deve corrigir em vez de capturar.
Tópicos Relacionados
- Erros no PHP — a diferença entre erros e exceções.
- Instrução
tryno PHP — uma análise detalhada da construçãotry. set_exception_handler()— um fallback global para exceções não capturadas.- Classes e Objetos no PHP — necessário para construir classes de exceção personalizadas.
- Funções PHP — onde exceções são mais frequentemente lançadas.
Conclusão
Exceções oferecem ao PHP uma maneira estruturada de lidar com falhas: uma função throw (lança) quando não pode continuar, e o chamador catch (captura) para recuperar, registrar ou relançar. Combine try, catch e finally para separar o caminho feliz do tratamento de erros e da limpeza, use classes personalizadas para modelar as falhas do seu domínio, e lembre-se de que problemas no nível do motor chegam como Error (capturáveis via Throwable). Praticar esses padrões em seus próprios projetos tornará seu código muito mais robusto.