Construye una estrategia de errores completa: excepciones de negocio encadenadas, un finally controlado y manejadores globales como última línea de defensa.
Abrir esta lección en KodokonDesde PHP 7, todo lo que se lanza implementa Throwable, con dos ramas: Error (fallos del motor y de tipado, como TypeError) y Exception (fallos de la aplicación). Solo capturas Error en los límites del programa. Del lado de la aplicación, la SPL proporciona una jerarquía lista para usar: LogicException señala un error del desarrollador, que hay que corregir; RuntimeException, una contingencia en tiempo de ejecución, que hay que manejar. El reflejo profesional: deriva tus excepciones de negocio de estas bases, una por cada situación identificable.
<?php
declare(strict_types=1);
abstract class AppException extends RuntimeException
{
}
final class UserNotFound extends AppException
{
public static function withEmail(
string $email
): self {
return new self("No user for $email");
}
}
try {
throw UserNotFound::withEmail('lea@example.com');
} catch (UserNotFound $e) {
echo $e->getMessage();
}try/catch solo merece la pena si sabes qué hacer con el error - de lo contrario, deja que suba. Tres herramientas refinan el control: el multi-catch catch (JsonException | ValueError $e) agrupa un manejo idéntico; el parámetro previous encadena la causa original cuando traduces una excepción técnica en una de negocio; finally se ejecuta en todos los casos - éxito, excepción, incluso un return anticipado - ideal para liberar un recurso.
<?php
declare(strict_types=1);
final class PayloadInvalid extends RuntimeException
{
}
function decode(string $json): mixed
{
try {
return json_decode(
$json,
true,
flags: JSON_THROW_ON_ERROR,
);
} catch (JsonException $e) {
throw new PayloadInvalid(
'Invalid JSON payload',
previous: $e,
);
} finally {
echo "decode() finished\n";
}
}
try {
decode('{broken');
} catch (PayloadInvalid $e) {
echo $e->getPrevious()?->getMessage();
}Al final de la cadena, dos manejadores globales cierran el montaje. set_exception_handler captura todo lo que no se manejó: registro estructurado, una respuesta 500 genérica - sin revelar nunca al usuario el mensaje ni la traza. set_error_handler convierte los errores heredados (warnings, notices) en ErrorException, unificando los dos mundos: todo se convierte en una excepción, todo sigue el mismo camino de manejo.
<?php
declare(strict_types=1);
set_error_handler(function (
int $severity,
string $message,
string $file,
int $line,
): bool {
throw new ErrorException(
$message,
0,
$severity,
$file,
$line,
);
});
set_exception_handler(function (Throwable $e): void {
error_log($e->getMessage());
http_response_code(500);
echo 'A technical error occurred.';
});
trigger_error('Legacy warning', E_USER_WARNING);
echo 'Never reached';Error y Exception en el PHP moderno?Error hereda de ExceptionThrowablefinally?previous de una excepción?