Introduction : Pourquoi la gestion basique des erreurs n'est que le début
Chaque développeur PHP connaît la construction try/catch. Mais lorsque le projet atteint des milliers de lignes de code et que la charge serveur devient élevée, une simple interception des exceptions ne suffit pas. La gestion avancée des erreurs n'est pas simplement « attraper et oublier », mais tout un système : de la journalisation à la transformation des avertissements en exceptions.
Dans cet article, nous aborderons les techniques qui vous aideront à écrire un code fiable et résilient : blocs catch multiples, classes d'exceptions personnalisées, gestionnaires globaux et intégration avec les journaux PSR-3. Ce contenu est destiné aux développeurs déjà familiers avec les bases de PHP.
1. Blocs catch multiples et hiérarchie des exceptions
Depuis PHP 7.1, vous pouvez intercepter différents types d'exceptions dans un seul bloc try. Cela permet de réagir de manière ciblée aux erreurs :
<?phpclass DatabaseException extends \\Exception {}class ValidationException extends \\Exception {}
try { // code pouvant lancer différentes exceptions $user = $db->query('SELECT ...'); if (!$user) { throw new DatabaseException('Erreur de requête'); } if (empty($user['email'])) { throw new ValidationException('Email obligatoire'); }} catch (DatabaseException $e) { // journalisation de l'erreur de base de données error_log('DB Error: ' . $e->getMessage()); echo 'Erreur temporaire du serveur. Veuillez réessayer plus tard.';} catch (ValidationException $e) { // affichage d'un message compréhensible à l'utilisateur echo 'Erreur : ' . htmlspecialchars($e->getMessage());} catch (\\Throwable $e) { // interception de tout le reste (y compris Error) error_log('Critical: ' . $e->getMessage()); echo 'Erreur critique.';}?>Pourquoi est-ce important ? Chaque type d'exception nécessite une réaction spécifique. Erreur de base de données — masquer les détails à l'utilisateur, erreur de validation — afficher le formulaire avec le champ en surbrillance, erreur critique — envoyer une notification à l'administrateur.
Notez l'utilisation de \\Throwable — c'est l'interface implémentée à la fois par Exception et Error (erreurs fatales PHP). Utilisez-la dans le dernier bloc catch pour ne manquer aucune erreur.
2. Classes d'exceptions personnalisées : étendre les standards
La classe standard \\Exception offre des fonctionnalités de base. Mais dans les projets réels, il est pratique de créer ses propres hiérarchies d'exceptions — cela simplifie le débogage et la gestion.
Exemple de structure pour une application web :
<?phpnamespace App\\Exceptions;
// Exception de base de l'applicationclass 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; }}
// Exception pour les erreurs 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; }}
// Utilisationthrow new HttpException(404, 'Page non trouvée', ['uri' => $_SERVER['REQUEST_URI']]);?>Avantages :
- Possibilité de transmettre un contexte supplémentaire (paramètres de requête, ID utilisateur) — cela simplifie la journalisation.
- Les exceptions sont regroupées par sens :
HttpException,ValidationException,PaymentException.