set_exception_handler()
Cómo set_exception_handler() de PHP registra un manejador global para excepciones no capturadas, con firma, valor de retorno, ejemplo y buenas prácticas.
Introducción
set_exception_handler() registra una función que PHP invoca cada vez que una excepción no capturada llega al nivel superior del script. Normalmente una excepción no capturada produce un error fatal y un volcado de pila predeterminado; un manejador global permite reemplazar eso con registro consistente, una página de error amigable o alertas — en un solo lugar, para toda la aplicación. Esta página cubre la firma de la función, lo que devuelve, un ejemplo ejecutable, los casos que no cubre y los puntos a tener en cuenta.
Si necesitas antes los conceptos básicos de lanzar y capturar excepciones, comienza con Excepciones en PHP y el capítulo try/catch.
¿Cuándo se llama al manejador?
Una excepción normal es capturada por el bloque catch más cercano que coincida. El manejador global solo se ejecuta cuando ningún bloque catch coincide — la excepción "escapa" hasta el nivel superior del script:
try {
throw new RuntimeException('handled here');
} catch (RuntimeException $e) {
// caught locally — the global handler never runs
}
throw new RuntimeException('nothing catches this'); // → global handler runs, then script endsDespués de que el manejador retorna, la ejecución no se reanuda — el script termina. Por lo tanto, el manejador es tu última oportunidad para registrar y presentar el fallo de forma limpia, no una manera de recuperarse y continuar.
Firma y valor de retorno
set_exception_handler(?callable $callback): ?callable$callback— un callable que acepta el objeto lanzado como único argumento. Desde PHP 7 toda excepción y error implementaThrowable, por lo que debes indicar el tipo del parámetro comoThrowable(no soloException) para capturar también instancias deErrorcomoTypeError.- Devuelve el manejador previamente registrado (o
nullsi no había ninguno), que puedes conservar para restaurarlo después. Pasarnullelimina el manejador.
Ejemplo ejecutable
El script a continuación registra un manejador, lo activa con una excepción no capturada e imprime un mensaje formateado. Escribe en el error estándar mediante error_log() sin destino, por lo que es totalmente portable:
<?php
function appExceptionHandler(Throwable $e): void
{
$message = sprintf(
"Uncaught %s: %s in %s on line %d",
get_class($e),
$e->getMessage(),
$e->getFile(),
$e->getLine()
);
error_log($message); // goes to the SAPI error log / stderr
echo "Something went wrong.\n"; // user-facing message
}
set_exception_handler('appExceptionHandler');
throw new RuntimeException('Database is unreachable');Salida (la línea de error_log va a stderr, el echo a stdout):
Something went wrong.con una línea como Uncaught RuntimeException: Database is unreachable in /path/to/script.php on line 19 en el registro de errores.
Lo que NO maneja
set_exception_handler() solo intercepta excepciones no capturadas. No captura:
- Errores fatales, errores de análisis o advertencias — esos pasan por
set_error_handler()(para errores capturables) oregister_shutdown_function()(para errores fatales). - Excepciones que ya son capturadas por un bloque
try/catchlocal.
Para errores que no son excepciones, como advertencias y avisos, registra un manejador separado con set_error_handler().
Restaurar el manejador anterior
restore_exception_handler() revierte al manejador que estaba activo antes de tu última llamada a set_exception_handler(). Úsalo cuando un manejador personalizado deba aplicarse solo a un bloque específico de código:
<?php
set_exception_handler(function (Throwable $e) {
echo "Custom: {$e->getMessage()}\n";
});
// ... code that should use the custom handler ...
restore_exception_handler(); // back to the default behaviorImportante: tu manejador no debe lanzar una nueva excepción. Si lo hace, PHP no puede despacharla de nuevo y genera un error fatal en su lugar.
Buenas prácticas para usar set_exception_handler
Al usar set_exception_handler, hay algunas buenas prácticas que debes seguir para garantizar que tu aplicación maneje los errores de manera efectiva:
- Indica el tipo del parámetro del manejador como
Throwablepara capturar tanto subtipos deExceptioncomo deError(PHP 7+). - Asegúrate de que el manejador nunca lance una nueva excepción — eso genera un error fatal irrecuperable.
- Registra suficiente contexto para diagnosticar el fallo: clase de la excepción, mensaje, archivo, línea y el seguimiento de pila de
$e->getTraceAsString(). - Mantén el mensaje orientado al usuario de forma genérica; nunca expongas trazas de pila ni mensajes a los usuarios finales en producción.
- Registra el manejador lo antes posible (por ejemplo, en un archivo de arranque) para que cubra toda la solicitud.
- Combínalo con
set_error_handler()yregister_shutdown_function()para cubrir también advertencias, avisos y errores fatales. - Usa
restore_exception_handler()para revertir al manejador anterior cuando uno personalizado deba estar limitado a un bloque de código.
Conclusión
set_exception_handler() te ofrece un único lugar para manejar todas las excepciones no capturadas en una aplicación — convirtiendo un error fatal en bruto en registro consistente y un mensaje limpio para el usuario. Recuerda sus límites: solo se ejecuta para excepciones no capturadas, la ejecución se detiene después, y el manejador en sí nunca debe lanzar. Combínalo con set_error_handler() para advertencias, trigger-error para señales de error personalizadas, y restore_exception_handler() para manejo con alcance limitado, y así construir un reporte de errores robusto.