throw
Em PHP, a palavra-chave "throw" é usada para lançar uma exceção. Aprenda a sintaxe, exemplos e boas práticas neste artigo.
A Palavra-chave throw do PHP
A palavra-chave throw interrompe a execução normal no ponto em que é executada e lança uma exceção — um objeto que sinaliza que algo deu errado. O controle salta imediatamente para fora da função atual e sobe pela pilha de chamadas até encontrar um bloco catch correspondente. Se nenhum catch corresponder, o PHP encerra o script com um erro fatal.
Esta página aborda a sintaxe de throw, quando usá-lo em vez de retornar um valor de erro, como lançar exceções embutidas e personalizadas, relançamento e encadeamento, e o recurso do PHP 8 que permite usar throw como expressão. Para uma visão mais ampla, consulte Exceções em PHP e o fluxo try/catch/finally.
Sintaxe
throw new Exception("Error message here");throw deve receber um valor que seja uma instância de Throwable — na prática, uma Exception (ou uma de suas subclasses) ou um Error. A string passada ao construtor se torna a mensagem da exceção, que você lê posteriormente com getMessage().
Como uma exceção lançada desfaz a pilha, qualquer código após throw no mesmo bloco nunca é executado:
throw new Exception("stop here");
echo "this line is unreachable"; // never executesPor que usar throw em vez de retornar um erro?
Retornar um valor especial (como false ou -1) para sinalizar falha obriga cada chamador a lembrar de verificá-lo, e o significado do valor é fácil de perder. throw torna a falha impossível de ignorar: a exceção se propaga automaticamente até que algo a trate, e carrega uma mensagem, um código, um rastreamento de pilha, além do arquivo e linha onde ocorreu.
Use throw para condições excepcionais das quais a função atual não consegue se recuperar de forma sensata — argumentos inválidos, uma conexão de banco de dados com falha, um arquivo obrigatório ausente — e deixe um chamador em nível superior decidir o que fazer.
Um exemplo básico
Aqui, uma função divide() lança uma exceção ao ser solicitada a dividir por zero, e o chamador a captura:
<?php
function divide(int $numerator, int $denominator): float
{
if ($denominator === 0) {
throw new InvalidArgumentException("Cannot divide by zero.");
}
return $numerator / $denominator;
}
try {
echo divide(10, 2), PHP_EOL; // 5
echo divide(10, 0), PHP_EOL; // throws before printing
} catch (InvalidArgumentException $e) {
echo "Caught: " . $e->getMessage() . PHP_EOL;
}Saída:
5
Caught: Cannot divide by zero.A primeira chamada é bem-sucedida e imprime 5. A segunda chamada lança uma exceção, portanto seu echo nunca é executado e o controle vai direto para o bloco catch.
Lançando uma exceção personalizada
Estender Exception permite dar a cada tipo de erro seu próprio nome, para que os chamadores possam capturar exatamente as falhas que lhes interessam e ignorar o resto:
<?php
class InsufficientFundsException extends Exception {}
function withdraw(float $balance, float $amount): float
{
if ($amount > $balance) {
throw new InsufficientFundsException(
"Cannot withdraw $amount; balance is only $balance."
);
}
return $balance - $amount;
}
try {
echo withdraw(100, 250), PHP_EOL;
} catch (InsufficientFundsException $e) {
echo "Declined: " . $e->getMessage() . PHP_EOL;
}Saída:
Declined: Cannot withdraw 250; balance is only 100.Consulte Classes de exceção personalizadas para saber mais sobre como estender Exception.
Mensagem, código e exceção anterior
O construtor de Exception aceita três argumentos — message, code e uma exceção previous. O terceiro permite encapsular um erro de baixo nível em um mais significativo sem perder a causa original (isso é chamado de encadeamento de exceções):
<?php
try {
try {
throw new RuntimeException("Disk read failed", 13);
} catch (RuntimeException $low) {
// Re-throw a higher-level exception, keeping the original as the cause.
throw new Exception("Could not load config", 0, $low);
}
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL; // Could not load config
echo "Caused by: " . $e->getPrevious()->getMessage() . PHP_EOL; // Disk read failed
echo "Original code: " . $e->getPrevious()->getCode() . PHP_EOL; // 13
}Saída:
Could not load config
Caused by: Disk read failed
Original code: 13Relançando em um bloco catch
Você não precisa tratar completamente uma exceção onde a captura. Um bloco catch pode fazer algum trabalho (registrá-la, adicionar contexto) e então throw novamente para deixar um tratador externo concluir o trabalho:
<?php
function loadUser(int $id): array
{
try {
throw new RuntimeException("Database is down");
} catch (RuntimeException $e) {
error_log("loadUser($id) failed: " . $e->getMessage());
throw $e; // pass it on
}
}
try {
loadUser(7);
} catch (RuntimeException $e) {
echo "Handled at top level: " . $e->getMessage() . PHP_EOL;
}Saída:
Handled at top level: Database is downthrow como expressão (PHP 8+)
Desde o PHP 8.0, throw é uma expressão, não apenas uma instrução, portanto você pode usá-lo em lugares que esperam um valor — como os operadores ?: e ?? ou uma arrow function:
<?php
function getConfig(array $config, string $key): string
{
// Throw inline when the key is missing.
return $config[$key] ?? throw new InvalidArgumentException("Missing key: $key");
}
echo getConfig(['env' => 'prod'], 'env'), PHP_EOL; // prod
try {
getConfig(['env' => 'prod'], 'region');
} catch (InvalidArgumentException $e) {
echo $e->getMessage() . PHP_EOL;
}Saída:
prod
Missing key: regionErros comuns
- Lançar sem um
try/catchem nenhum lugar acima na pilha. Uma exceção não capturada se torna um erro fatal e para o script. Sempre capture-a em algum lugar, ou registre um fallback comset_exception_handler(). - Lançar uma string ou array.
throwrequer um objeto implementandoThrowable;throw "oops";é um erro de sintaxe. - Engolir exceções silenciosamente. Um bloco
catchvazio oculta bugs. No mínimo, registre a mensagem, ou relance. - Usar exceções para fluxo de controle comum. Lançar em cada ramificação esperada (por exemplo, "usuário não encontrado" durante uma busca de rotina) é lento e confuso — reserve para casos genuinamente excepcionais.
Resumo
throwlança umThrowablee imediatamente desfaz a pilha até ocatchcorrespondente mais próximo.- Prefira-o a valores de retorno mágicos para que falhas não possam ser ignoradas silenciosamente.
- Crie subclasses de
Exceptionpara criar tipos de erro nomeados; passe uma exceçãopreviouspara encadear causas. - Capture, adicione contexto e
thrownovamente para deixar um tratador externo decidir. - No PHP 8+,
throwfunciona como expressão dentro de??,?:e arrow functions.
Continue com o bloco try, o bloco catch e finally para ver o ciclo completo de tratamento de exceções.