Introducción: Por qué el manejo básico de errores es solo el comienzo
Cada desarrollador PHP conoce la construcción try/catch. Pero cuando el proyecto crece a miles de líneas de código y la carga del servidor se vuelve alta, la simple captura de excepciones no es suficiente. El manejo avanzado de errores no es solo "atrapar y olvidar", sino un sistema completo: desde el registro hasta la transformación de advertencias en excepciones.
En este artículo, analizaremos técnicas que le ayudarán a escribir código robusto y tolerante a fallos: múltiples catch, clases de excepción personalizadas, manejadores globales e integración con registradores PSR-3. El material está dirigido a desarrolladores que ya conocen los fundamentos de PHP.
1. Múltiples bloques catch y jerarquía de excepciones
A partir de PHP 7.1, puede capturar diferentes tipos de excepciones en un solo bloque try. Esto permite reaccionar de forma precisa a los errores:
<?phpclass DatabaseException extends \\Exception {}class ValidationException extends \\Exception {}
try { // código que puede lanzar diferentes excepciones $user = $db->query('SELECT ...'); if (!$user) { throw new DatabaseException('Error de consulta'); } if (empty($user['email'])) { throw new ValidationException('Email es obligatorio'); }} catch (DatabaseException $e) { // registramos el error de BD error_log('Error BD: ' . $e->getMessage()); echo 'Error temporal del servidor. Intente más tarde.';} catch (ValidationException $e) { // mostramos al usuario un mensaje comprensible echo 'Error: ' . htmlspecialchars($e->getMessage());} catch (\\Throwable $e) { // capturamos todo lo demás (incluyendo Error) error_log('Crítico: ' . $e->getMessage()); echo 'Error crítico.';}?>¿Por qué es importante? Cada tipo de excepción requiere su propia reacción. Un error de BD: ocultar detalles al usuario, un error de validación: mostrar el formulario con el campo resaltado, un error crítico: enviar una notificación al administrador.
Observe \\Throwable — es la interfaz que implementan tanto Exception como Error (errores fatales de PHP). Úselo en el último bloque catch para no perderse ningún error.
2. Clases de excepción personalizadas: ampliando los estándares
La clase estándar \\Exception proporciona funcionalidad básica. Pero en proyectos reales es conveniente crear sus propias jerarquías de excepciones — esto simplifica la depuración y el manejo.
Ejemplo de estructura para una aplicación web:
<?phpnamespace App\\Exceptions;
// Excepción base de la aplicaciónclass AppException extends \\RuntimeException{ protected $context = [];
public function __construct(string $message = '', int $code = 0, ?\\Throwable $previous = null, array $context = []) { parent::__construct($message, $code, $previous); $this->context = $context; }
public function getContext(): array { return $this->context; }}
// Excepción para errores HTTPclass HttpException extends AppException{ private int $statusCode;
public function __construct(int $statusCode, string $message = '', array $context = []) { $this->statusCode = $statusCode; parent::__construct($message, $statusCode, null, $context); }
public function getStatusCode(): int { return $this->statusCode; }}
// Usothrow new HttpException(404, 'Página no encontrada', ['uri' => $_SERVER['REQUEST_URI']]);?>Ventajas:
- Se puede pasar contexto adicional (parámetros de solicitud, ID de usuario) — esto simplifica el registro.
- Las excepciones se agrupan por significado:
HttpException,ValidationException,PaymentException.