Gestion des erreurs en PHP : des constructions de base aux motifs professionnels
Tout développeur PHP rencontre tôt ou tard une situation où le code ne se comporte pas comme prévu. Fichier introuvable, base de données inaccessible, utilisateur ayant saisi des données incorrectes — ce sont toutes des situations exceptionnelles. Une gestion adéquate des erreurs transforme une application fragile en un système fiable. Dans cet article, nous aborderons tous les aspects de la gestion des erreurs en PHP : du simple try/catch à la création de classes d'exceptions personnalisées et de gestionnaires globaux.
1. Les bases : la construction try/catch et throw
En PHP, les exceptions sont des objets de la classe Exception (ou de ses descendants). Le mécanisme de base se compose de trois mots-clés :
try— le bloc dans lequel le code potentiellement dangereux est exécuté ;catch— le bloc qui intercepte l'exception ;throw— l'opérateur qui « lance » l'exception.
Examinons un exemple simple :
<?phpfunction divide($a, $b) { if ($b == 0) { throw new Exception('Division par zéro impossible'); } return $a / $b;}
try { echo divide(10, 0);} catch (Exception $e) { echo 'Erreur : ' . $e->getMessage();}?>Lorsque l'exécution atteint throw, PHP quitte immédiatement la fonction actuelle et cherche un bloc catch approprié. Si un catch est trouvé, l'exécution se poursuit à partir de celui-ci. Sinon, une erreur fatale se produit.
Important : à partir de PHP 7, la plupart des erreurs internes (par exemple, la division par zéro) lancent des exceptions de la classe DivisionByZeroError. Pour les intercepter, il faut spécifier le type correspondant.
2. Fonctionnalités avancées : catch multiples et finally
Il arrive souvent que différents types d'exceptions puissent survenir dans un même bloc try. PHP permet de créer plusieurs blocs catch pour différentes classes :
<?phpclass ValidationException extends Exception {}class DatabaseException extends Exception {}
try { // code pouvant lancer différentes exceptions} catch (ValidationException $e) { echo 'Erreur de validation : ' . $e->getMessage();} catch (DatabaseException $e) { echo 'Erreur de base de données : ' . $e->getMessage();} catch (Exception $e) { // Gestionnaire général pour toutes les autres exceptions echo 'Erreur inconnue : ' . $e->getMessage();}?>L'ordre des blocs catch est important : PHP les vérifie séquentiellement, et le premier correspondant au type intercepte l'exception. Par conséquent, le catch (Exception $e) général est toujours placé en dernier.
Le bloc finally s'exécute dans tous les cas — après la fin réussie du try, après l'interception d'une exception, et même si une instruction return est présente dans le catch. C'est l'endroit idéal pour fermer des fichiers, libérer des ressources ou écrire dans un journal :
<?phpfunction readConfig($filename) { $handle = fopen($filename, 'r'); if (!$handle) { throw new Exception('Impossible d\'ouvrir le fichier'); } try { // lecture des données return fread($handle, filesize($filename)); } finally { fclose($handle); // le fichier se fermera même en cas d'exception }}?>3. Classes d'exceptions personnalisées et gestionnaires globaux
La création de vos propres classes d'exceptions est un outil puissant pour structurer le code. Il suffit d'hériter de Exception :
<?phpclass InvalidEmailException extends Exception { public function __construct($email, $code = 0, Throwable $previous = null) { $message = "L'email '$email' a un format invalide"; parent::__construct($message, $code, $previous); }}
function validateEmail($ema