Una excepción personalizada es una clase de excepción propia que representa un fallo concreto del dominio de la aplicación.
Hasta ahora hemos usado la clase genérica Exception. Sin embargo, en aplicaciones reales, lanzar una Exception genérica para todo (error de base de datos, archivo no encontrado, usuario inválido) hace difícil manejar los errores de forma inteligente.
Las excepciones personalizadas son clases que heredan de Exception y representan problemas específicos del dominio de la aplicación.
¿Por qué hacerlo?
Imagina que estás procesando un pago. No es lo mismo un error por “Tarjeta rechazada” (quieres pedir otra tarjeta) que un error por “Servidor del banco caído” (quieres intentar de nuevo más tarde). Si ambos son solo Exception, es difícil distinguirlos en el catch.
Sintaxis básica
Para crear una excepción personalizada, simplemente creas una clase que extienda (herede) de la clase base de PHP.
// Definición básica
class MiErrorPersonalizado extends Exception {
// Hereda automáticamente getMessage(), getCode(), etc.
// Puedes agregar métodos propios si lo necesitas.
}Ejemplo práctico: sistema de login
Vamos a simular un sistema de login donde pueden fallar dos cosas distintas: que el email no exista o que la contraseña esté mal. Crearemos una excepción para cada caso.
1. Definimos las excepciones
class EmailNoEncontradoException extends Exception {}
class PasswordIncorrectoException extends Exception {}2. Función que lanza errores específicos
function loguearUsuario($email, $password) {
// Base de datos simulada
$dbEmail = "[email protected]";
$dbPass = "1234";
if ($email !== $dbEmail) {
// Lanzamos el error específico de email
throw new EmailNoEncontradoException("El correo $email no existe en el sistema.");
}
if ($password !== $dbPass) {
// Lanzamos el error específico de contraseña
throw new PasswordIncorrectoException("La contraseña ingresada no es válida.");
}
return "¡Bienvenido al sistema!";
}3. Captura selectiva (Multi-Catch)
Podemos tener varios bloques catch para reaccionar de forma distinta según la clase de la excepción.
try {
// Intentamos loguear (cambia los valores para probar distintos errores)
echo loguearUsuario("[email protected]", "clave_erronea");
} catch (EmailNoEncontradoException $e) {
// Lógica A: Quizás redirigir al registro
echo "Error de Usuario: " . $e->getMessage();
echo "\n -> ¿Quieres registrarte?";
} catch (PasswordIncorrectoException $e) {
// Lógica B: Quizás mostrar botón de 'recuperar contraseña'
echo "Error de Seguridad: " . $e->getMessage();
echo "\n -> Inténtalo de nuevo o recupera tu clave.";
} catch (Exception $e) {
// Lógica C: Un catch genérico por si ocurre algo imprevisto no personalizado
echo "Error desconocido: " . $e->getMessage();
}Ventajas
- Claridad Semántica: El código se lee mejor (
catch (EmailNoEncontrado...)es más claro quecatch (Exception...)). - Control Granular: Puedes tomar decisiones de negocio diferentes para cada error sin tener que hacer
if ($e->getMessage() == '...'). - Extensibilidad: Tus excepciones personalizadas pueden tener sus propios métodos (por ejemplo,
TarjetaRechazadaExceptionpodría tener un método$e->getBancoEmisor()).