Entendiendo las Excepciones en PHP
En PHP, las excepciones se usan para manejar errores inesperados y problemas en tiempo de ejecución. Aprende a lanzar, capturar y crear excepciones.
Una excepción es un objeto que representa un error o una condición inesperada que interrumpe el flujo normal de tu programa. En lugar de devolver un código de error que el llamador podría olvidar comprobar, el código "lanza" una excepción; el entorno de ejecución entonces deshace la pila de llamadas hasta encontrar un bloque catch coincidente. Si ningún bloque la captura, el script se detiene con un error fatal.
Este capítulo cubre cómo lanzar y capturar excepciones, los métodos que expone toda excepción (getMessage(), getCode(), getLine(), getFile()), el bloque finally, múltiples bloques catch, clases de excepción personalizadas y la diferencia entre Exception y Error.
¿Qué es una Excepción en PHP?
Una excepción en PHP es un objeto que desciende de la clase integrada Exception (o, de forma más amplia, de la interfaz Throwable). Cuando algo falla — un archivo que no existe, un argumento no válido, una conexión a la base de datos fallida — se crea uno de estos objetos y se lanza con throw. Lanzar detiene inmediatamente la ruta de ejecución actual y transfiere el control al manejador envolvente más cercano.
Usa una excepción cuando una función no puede continuar de forma significativa y el llamador es el lugar adecuado para decidir qué hacer a continuación. No las uses para el flujo de control ordinario (una búsqueda normal de "usuario no encontrado" se expresa mejor con un valor de retorno).
Lanzar una Excepción
La palabra clave throw genera una excepción, seguida de una nueva instancia de una clase de excepción. El constructor acepta un mensaje opcional, un código entero y una excepción anterior (para encadenamiento):
<?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();
}
?>Salida:
Error: Division by zero is not allowed.El código dentro de try se ejecuta normalmente hasta que se dispara throw. A partir de ese punto, el resto del bloque try se omite y se ejecuta el bloque catch correspondiente.
Manejo de Excepciones con try / catch
Se envuelve el código que podría fallar en un bloque try y se recupera del fallo en un bloque catch. La variable en catch (aquí $e) contiene el objeto de excepción, que expone varios métodos de solo lectura:
| Método | Devuelve |
|---|---|
getMessage() | El mensaje legible por humanos |
getCode() | El código entero pasado al constructor |
getLine() | La línea donde se lanzó la excepción |
getFile() | El archivo donde se lanzó |
getPrevious() | La excepción "anterior" encadenada, si existe |
getTraceAsString() | La traza de la pila como cadena de texto |
<?php
try {
throw new Exception('Something failed', 42);
} catch (Exception $e) {
echo 'Message: ' . $e->getMessage() . PHP_EOL;
echo 'Code: ' . $e->getCode() . PHP_EOL;
}
?>Salida:
Message: Something failed
Code: 42Captura de Múltiples Tipos de Excepciones
Un único bloque try puede tener varios bloques catch. PHP los verifica de arriba a abajo y ejecuta el primero cuyo tipo coincide. Desde PHP 7.1 también se pueden capturar varios tipos no relacionados en un bloque usando el operador tubería (|):
<?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();
}
?>Salida:
Runtime/logic problem: Network is downEl orden importa: lista los tipos de excepción más específicos antes que sus clases padre, de lo contrario el catch genérico lo absorberá todo primero.
El Bloque finally
El bloque finally es opcional pero útil. Su código siempre se ejecuta — tanto si se lanzó una excepción como si no, e incluso si el bloque try o catch ejecuta un return. Esto lo convierte en el lugar adecuado para tareas de limpieza como cerrar un manejador de archivos o liberar un bloqueo:
<?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;
}
?>Salida:
Open resource
Caught: Boom
Cleanup always runsClases de Excepción Personalizadas
Más allá de los tipos integrados, puedes definir tus propias clases de excepción extendiendo Exception. Una clase personalizada te permite llevar datos adicionales (como un valor fallido) y permite a los llamadores capturar tu tipo de error específico sin atrapar accidentalmente otros no 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.';
}
?>Salida:
Short by 25.5
Need 25.5 more.PHP también incluye una familia de excepciones SPL ya listas — InvalidArgumentException, RuntimeException, LengthException y otras — por lo que a menudo no necesitas crear las tuyas propias.
Exception vs. Error
Desde PHP 7, los fallos internos del motor (como un error de tipo o llamar a un método no definido) se lanzan como objetos Error, no como objetos Exception. Ambos implementan la interfaz Throwable. Un simple catch (Exception $e) no capturará un Error. Para manejar ambos, captura la interfaz:
<?php
try {
$result = 10 % 0; // throws a DivisionByZeroError
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage();
}
?>Salida:
DivisionByZeroError: Modulo by zeroComo regla general, reserva Exception para problemas de los que tu aplicación puede recuperarse, y deja que Error represente errores que deberías corregir en lugar de capturar.
Temas Relacionados
- Errores en PHP — la diferencia entre errores y excepciones.
- Sentencia
tryen PHP — un enfoque detallado sobre la construccióntry. set_exception_handler()— un respaldo global para excepciones no capturadas.- Clases y Objetos en PHP — necesario para construir clases de excepción personalizadas.
- Funciones en PHP — donde con mayor frecuencia se lanzan las excepciones.
Conclusión
Las excepciones proporcionan a PHP una forma estructurada de tratar los fallos: una función lanza con throw cuando no puede continuar, y el llamador usa catch para recuperarse, registrar o relanzar. Combina try, catch y finally para separar el camino feliz del manejo de errores y la limpieza, usa clases personalizadas para modelar los fallos de tu dominio y recuerda que los problemas a nivel del motor llegan como Error (capturable vía Throwable). Practicar estos patrones en tus propios proyectos hará que tu código sea mucho más robusto.