Comprendre les exceptions PHP
En PHP, les exceptions permettent de gérer les erreurs inattendues et les problèmes d'exécution de façon structurée avec try, catch et finally.
Une exception est un objet qui représente une erreur ou une condition inattendue interrompant le déroulement normal de votre programme. Au lieu de retourner un code d'erreur que l'appelant pourrait oublier de vérifier, le code « lève » une exception ; l'exécution déroule alors la pile d'appels jusqu'à trouver un bloc catch correspondant. Si aucun bloc ne la capture, le script s'arrête avec une erreur fatale.
Ce chapitre explique comment lever et capturer des exceptions, les méthodes exposées par chaque exception (getMessage(), getCode(), getLine(), getFile()), le bloc finally, les blocs catch multiples, les classes d'exceptions personnalisées et la différence entre Exception et Error.
Qu'est-ce qu'une exception PHP ?
Une exception PHP est un objet qui descend de la classe intégrée Exception (ou, plus généralement, de l'interface Throwable). Quand quelque chose se passe mal — un fichier manquant, un argument invalide, une connexion à la base de données échouée — vous créez l'un de ces objets et le throw (lancez). Lancer une exception arrête immédiatement le chemin d'exécution en cours et passe le contrôle au gestionnaire englobant le plus proche.
Utilisez une exception lorsqu'une fonction ne peut pas continuer de façon significative et que c'est l'appelant qui doit décider quoi faire ensuite. N'en utilisez pas pour un flux de contrôle ordinaire (une recherche normale « utilisateur introuvable » s'exprime mieux avec une valeur de retour).
Lever une exception
Le mot-clé throw lève une exception, suivi d'une nouvelle instance d'une classe d'exception. Le constructeur accepte un message optionnel, un code entier et une exception précédente (pour le chaînage) :
<?php
function divide(int $a, int $b): float
{
if ($b === 0) {
throw new InvalidArgumentException('Division by zero is not allowed.');
}
return $a / $b;
}
try {
echo divide(10, 0);
} catch (InvalidArgumentException $e) {
echo 'Error: ' . $e->getMessage();
}
?>Résultat :
Error: Division by zero is not allowed.Le code à l'intérieur de try s'exécute normalement jusqu'à ce que throw se déclenche. À partir de ce moment, le reste du bloc try est ignoré et le bloc catch correspondant s'exécute.
Gérer les exceptions avec try / catch
Vous encadrez le code susceptible d'échouer dans un bloc try et récupérez l'échec dans un bloc catch. La variable dans catch (ici $e) contient l'objet exception, qui expose plusieurs méthodes en lecture seule :
| Méthode | Retourne |
|---|---|
getMessage() | Le message lisible par l'humain |
getCode() | Le code entier passé au constructeur |
getLine() | La ligne où l'exception a été levée |
getFile() | Le fichier où elle a été levée |
getPrevious() | L'exception « précédente » chaînée, le cas échéant |
getTraceAsString() | La trace de pile sous forme de chaîne |
<?php
try {
throw new Exception('Something failed', 42);
} catch (Exception $e) {
echo 'Message: ' . $e->getMessage() . PHP_EOL;
echo 'Code: ' . $e->getCode() . PHP_EOL;
}
?>Résultat :
Message: Something failed
Code: 42Capturer plusieurs types d'exceptions
Un seul bloc try peut avoir plusieurs blocs catch. PHP les vérifie du haut vers le bas et exécute le premier dont le type correspond. Depuis PHP 7.1, vous pouvez également capturer plusieurs types non liés dans un seul bloc avec l'opérateur pipe (|) :
<?php
try {
throw new RuntimeException('Network is down');
} catch (InvalidArgumentException $e) {
echo 'Bad argument: ' . $e->getMessage();
} catch (RuntimeException | LogicException $e) {
echo 'Runtime/logic problem: ' . $e->getMessage();
}
?>Résultat :
Runtime/logic problem: Network is downL'ordre est important : listez les types d'exceptions plus spécifiques avant leurs classes parentes, sinon le catch général engloutit tout en premier.
Le bloc finally
Le bloc finally est optionnel mais utile. Son code s'exécute toujours — qu'une exception ait été levée ou non, et même si le bloc try ou catch exécute un return. C'est donc l'endroit idéal pour le nettoyage, comme la fermeture d'un descripteur de fichier ou la libération d'un verrou :
<?php
try {
echo 'Open resource' . PHP_EOL;
throw new Exception('Boom');
} catch (Exception $e) {
echo 'Caught: ' . $e->getMessage() . PHP_EOL;
} finally {
echo 'Cleanup always runs' . PHP_EOL;
}
?>Résultat :
Open resource
Caught: Boom
Cleanup always runsClasses d'exceptions personnalisées
Au-delà des types intégrés, vous pouvez définir vos propres classes d'exceptions en étendant Exception. Une classe personnalisée vous permet de transporter des données supplémentaires (comme une valeur qui a échoué) et permet aux appelants de catcher votre type d'erreur spécifique sans capturer accidentellement des erreurs non liées :
<?php
class InsufficientFundsException extends Exception
{
private float $shortfall;
public function __construct(float $shortfall)
{
$this->shortfall = $shortfall;
parent::__construct("Short by $shortfall");
}
public function getShortfall(): float
{
return $this->shortfall;
}
}
try {
throw new InsufficientFundsException(25.5);
} catch (InsufficientFundsException $e) {
echo $e->getMessage() . PHP_EOL;
echo 'Need ' . $e->getShortfall() . ' more.';
}
?>Résultat :
Short by 25.5
Need 25.5 more.PHP fournit également une famille d'exceptions SPL prêtes à l'emploi — InvalidArgumentException, RuntimeException, LengthException, et d'autres — vous n'avez donc souvent pas besoin d'en inventer de nouvelles.
Exception vs. Error
Depuis PHP 7, les échecs internes du moteur (comme une erreur de type ou l'appel d'une méthode indéfinie) sont lancés sous forme d'objets Error, non d'objets Exception. Les deux implémentent l'interface Throwable. Un simple catch (Exception $e) ne capturera pas une Error. Pour gérer les deux, capturez l'interface :
<?php
try {
$result = 10 % 0; // throws a DivisionByZeroError
} catch (Throwable $e) {
echo get_class($e) . ': ' . $e->getMessage();
}
?>Résultat :
DivisionByZeroError: Modulo by zeroEn règle générale, réservez Exception aux problèmes dont votre application peut se remettre, et laissez Error représenter des bogues à corriger plutôt qu'à capturer.
Sujets connexes
- Erreurs PHP — la différence entre les erreurs et les exceptions.
- L'instruction PHP
try— un regard ciblé sur la constructiontry. set_exception_handler()— une solution de secours globale pour les exceptions non capturées.- Classes et objets PHP — nécessaires pour construire des classes d'exceptions personnalisées.
- Fonctions PHP — là où les exceptions sont le plus souvent levées.
Conclusion
Les exceptions offrent à PHP une façon structurée de gérer les échecs : une fonction throwe quand elle ne peut pas continuer, et l'appelant catche pour récupérer, journaliser ou relancer. Combinez try, catch et finally pour séparer le chemin heureux de la gestion des erreurs et du nettoyage, utilisez des classes personnalisées pour modéliser les échecs de votre domaine, et n'oubliez pas que les problèmes au niveau du moteur arrivent sous forme d'Error (capturable via Throwable). Pratiquer ces patterns dans vos propres projets rendra votre code bien plus robuste.