Gestion des erreurs en PHP : try/catch et au-delà
La gestion des erreurs est l'une des tâches clés de tout développeur web. Un code PHP bien écrit n'exécute pas seulement la logique métier, mais réagit également correctement aux situations imprévues : fichier manquant, problèmes de base de données, saisie utilisateur incorrecte. Dans cet article, nous allons détailler le fonctionnement de la gestion des erreurs en PHP, en commençant par les bases du try/catch jusqu'aux techniques avancées — exceptions personnalisées et gestionnaires globaux.
1. Les bases : la structure try/catch
La façon la plus courante de gérer les erreurs en PHP moderne est la structure try/catch. Elle permet d'« attraper » une exception (un objet de la classe Throwable ou de ses héritiers) et d'exécuter un code alternatif au lieu d'une terminaison brutale du script.
La syntaxe de base ressemble à ceci :
<?phptry { // Code qui peut lancer une exception $file = fopen('data.txt', 'r'); if (!$file) { throw new Exception('Impossible d\'ouvrir le fichier'); } // Travail avec le fichier...} catch (Exception $e) { // Gestion de l'erreur echo 'Une erreur est survenue : ' . $e->getMessage();}?>Dans le bloc try, on place le code potentiellement dangereux. Si une exception survient à l'intérieur (via throw ou à cause d'une erreur interne de PHP), l'exécution passe immédiatement au bloc catch. La variable $e contient l'objet exception, sur lequel on peut appeler les méthodes :
getMessage()— le texte de l'erreur ;getCode()— le code numérique de l'erreur ;getFile()— le fichier où l'erreur s'est produite ;getLine()— la ligne qui a provoqué l'erreur.
2. Le bloc finally : un code qui s'exécute toujours
Il est parfois nécessaire d'exécuter certaines actions indépendamment du fait qu'une erreur se soit produite ou non — par exemple, fermer une connexion à la base de données ou libérer des ressources. Pour cela, on utilise le bloc finally :
<?phpfunction processData($data) { try { // Opération dangereuse if (empty($data)) { throw new InvalidArgumentException('Les données ne peuvent pas être vides'); } echo "Traitement des données..."; return true; } catch (InvalidArgumentException $e) { echo "Erreur : " . $e->getMessage() . ""; return false; } finally { echo "Le bloc finally s'exécute toujours."; }}
processData([]); // Affichera : Erreur : Les données ne peuvent pas être vides, puis le bloc finallyprocessData('test'); // Affichera : Traitement des données..., puis le bloc finally?>Le bloc finally s'exécute même si un opérateur return est présent dans try ou catch. Cela garantit le nettoyage des ressources.
3. Exceptions personnalisées : étendre la classe Exception
Dans les projets réels, on se contente rarement de la classe standard Exception. Il est bien plus pratique de créer ses propres classes d'exceptions pour différents types d'erreurs. Cela rend le code plus lisible et facilite la capture de situations spécifiques.
Exemple : créons une exception pour les erreurs de validation et une pour les erreurs de base de données.
<?phpclass ValidationException extends Exception {}class DatabaseException extends Exception {}
function validateUser($age) { if ($age < 0 || $age > 150) { throw new ValidationException('Âge incorrect'); } return true;}
function connectToDatabase($dsn) { if (empty($dsn)) { throw new DatabaseException('Le DSN ne peut pas être vide'); } // Simulation de connexion...}
try { validateUser(200);} catch (ValidationException $e) { echo 'Erreur de validation : ' . $e->getMessage();}
try { connectToDatabase('');} catch (DatabaseException $e) {