Comprendre le mécanisme
Les exceptions remontent la pile jusqu’à un catch compatible. Throwable couvre notamment Exception et Error. finally sert au nettoyage, y compris lorsqu’un return a été évalué ; un return dans finally peut remplacer le résultat et masquer un problème. Un avertissement de fonction historique n’est pas nécessairement une exception. Testez le contrat précis de l’API utilisée. Un fichier ou un flux ouvert a un propriétaire responsable de sa fermeture.
Raisonner et vérifier
Pour les échanges JSON, activez les erreurs explicites et validez ensuite la structure. Un décodage réussi ne garantit ni les champs ni les types attendus. Conservez les identifiants opaques comme chaînes et évitez les calculs financiers en flottants binaires. Une date locale sans fuseau n’identifie pas toujours un instant unique ; stockez le contexte nécessaire et comparez les instants appropriés.
La hiérarchie des erreurs capturables
Throwable constitue le contrat commun aux branches Error et Exception. Capturer seulement Exception ne couvre donc pas tout ce qui peut remonter comme Throwable. Choisissez la frontière de capture selon votre responsabilité : une erreur de programmation ne doit pas être silencieusement convertie en succès métier. Un gestionnaire global peut produire une réponse publique contrôlée tout en conservant un diagnostic privé pour l’investigation.
Understand this common mistake
catch Exception intercepte nécessairement tout Error.
La hiérarchie comporte des branches distinctes.
Traiter au niveau qui peut décider
Attraper une exception n’est pas encore la résoudre. Le niveau de traitement doit savoir s’il peut reprendre, annuler ou traduire l’échec. Un repository ne doit pas prétendre que la commande a réussi après une erreur de stockage. Conservez la cause utile au diagnostic, puis exposez un contrat d’erreur stable à la couche suivante. Les reprises doivent tenir compte des effets déjà appliqués avant l’exception.
Understand this common mistake
Ignorer toute exception assure une transaction correcte.
Le masquage peut cacher un état incohérent.
Le nettoyage ne doit pas changer le résultat
finally sert à exécuter un nettoyage dans le flux prévu, mais un return placé dans ce bloc peut remplacer un résultat ou masquer une exception. Gardez donc la libération des ressources séparée de la décision de succès. Dans un laboratoire, lancez une exception dans try puis ajoutez un return dans finally : observer la disparition de l’erreur montre pourquoi ce raccourci est dangereux pour une transaction.
Understand this common mistake
finally garantit le succès métier après une exception.
Le nettoyage ne prouve pas la réussite de l’opération.
Syntaxe JSON et modèle métier
Un document JSON valide peut contenir une chaîne là où le domaine demande un entier. Après le parsing, vérifiez clés, types, bornes et relations entre champs. Pour un identifiant plus grand que PHP_INT_MAX dont il faut garder tous les chiffres, définissez un contrat texte et utilisez les options de décodage adaptées, notamment JSON_BIGINT_AS_STRING. Convertir trop tôt en float peut perdre une information qui ne pourra plus être reconstruite exactement.
Understand this common mistake
json_decode réussi prouve toutes les clés métier.
Les types, clés et invariants demandent une validation.
Une erreur publique utile et limitée
Un client a besoin d’un code stable et d’une explication actionnable, pas des chemins internes, du DSN et des secrets de connexion. Séparez la réponse publique d’un événement privé corrélé. L’identifiant de corrélation peut être non sensible et borné. Testez les erreurs de validation et les pannes inattendues : le chemin exceptionnel ne doit pas devenir le seul endroit qui expose une trace complète ou des credentials.
Understand this common mistake
Une API doit afficher toute trace et tout DSN.
Ces informations appartiennent au diagnostic privé contrôlé.
Fermer selon le cycle de ressource
Un fichier, une connexion ou un flux possède une durée utile indépendante de la durée apparente de la fonction. Prévoyez la fermeture sur succès et sur échec, en respectant l’API concernée. Un nettoyage qui échoue peut lui-même demander un diagnostic sans masquer la cause initiale. Les tests doivent simuler une erreur pendant le traitement ; un seul chemin nominal ne démontre pas que la ressource est libérée au bon moment.
Understand this common mistake
Une exception rend inutile toute politique de fermeture.
Les chemins d’échec consomment aussi des ressources.
Reconnaître les conventions de retour
Les API ne signalent pas toutes un échec par une exception. Certaines retournent false, une valeur spéciale ou un code qu’il faut examiner. Lisez le contrat de la fonction puis utilisez une comparaison qui conserve les valeurs valides, notamment zéro. Évitez de transformer tout résultat faux au sens booléen en erreur : une recherche peut avoir réussi au premier indice. Le traitement doit distinguer cette réussite d’une absence réelle.
Understand this common mistake
Toute fonction signalant false lance toujours une exception.
Le mode d’erreur dépend de l’API et de sa configuration.
Valider avant les effets coûteux
Le parsing et la validation doivent précéder les effets qui ne peuvent pas être simplement annulés. Envoyer un email puis découvrir que l’adresse ou la permission était invalide laisse déjà une conséquence externe. Organisez le traitement en étapes : données structurées, invariants, droit, transition durable et effets coordonnés. Cette séparation permet de tester qu’un refus ne produit ni écriture ni appel aval interdit.
Understand this common mistake
Une entrée invalide peut être refusée après tout envoi externe.
L’ordre conditionne l’absence d’effet interdit.
Construire des classes d’entrées de test
Un exemple nominal ne couvre pas une frontière. Préparez une petite matrice contenant clé absente, null, valeur vide, mauvais type et valeurs aux bornes. Pour chaque cas, écrivez le résultat attendu et l’effet interdit. Cette démarche évite une accumulation d’exemples arbitraires : les tests représentent des distinctions du contrat, et leur nom explique pourquoi cette catégorie doit être acceptée ou refusée.
Understand this common mistake
Un exemple valide prouve tous les chemins d’erreur.
Les cas négatifs demandent leurs propres assertions.
La désérialisation ne donne pas la provenance
Lire une représentation ne démontre pas qui l’a produite. Une préférence contenue dans un cookie reste une entrée client même si elle a déjà été stockée auparavant. Dans une nouvelle API, préférez un format de données simple avec validation explicite plutôt que traiter librement une sérialisation d’objets non fiable. La reconstruction d’objets peut introduire des comportements et dépendances qui dépassent le besoin d’une préférence textuelle.
Understand this common mistake
Toute donnée désérialisée est authentifiée.
Lire une représentation ne prouve pas sa provenance.
Atelier guidé : lire, expliquer et vérifier le code
<?php
declare(strict_types=1);
$data = json_decode('{"amount":"12"}', true, flags: JSON_THROW_ON_ERROR);
echo is_int($data['amount']) ? 'accepted' : 'rejected'; Le document de l’exercice contient amount entre guillemets. Le parseur JSON établit que le document est syntaxiquement lisible ; il conserve ensuite amount comme une chaîne. is_int retourne false et le programme affiche rejected. Aucun JsonException n’est requis pour expliquer ce résultat : le défaut se situe dans le contrat métier du contenu, après le parsing réussi.
Rejouez le programme avec un entier positif, zéro, null et une clé absente. Ajoutez une garde de présence avant la lecture pour que le dernier cas soit traité proprement. Écrivez ensuite une matrice qui distingue rejet de type et rejet de borne. Si votre produit accepte volontairement une chaîne numérique, définissez la grammaire et les bornes de cette conversion au lieu de compter sur un cast implicite.
Préférences client : JSON, schéma et absence de privilège
$preferences = unserialize($_COOKIE["prefs"]); Un cookie est contrôlable par son porteur. Unserialize sur une entrée non fiable peut déclencher des comportements liés aux objets et à leurs méthodes magiques selon le code disponible ; ce n’est pas un simple décodeur de données interchangeables.
Pour une nouvelle implémentation de préférences, choisissez un format de données comme JSON, bornez taille et profondeur et validez un schéma étroit. Par exemple, theme peut appartenir à une liste claire et langue à une liste supportée. Une structure syntaxiquement correcte ne doit pas permettre d’introduire rôle, tenant ou chemin de fichier.
Les droits proviennent du contexte serveur authentifié et autorisé, jamais du nom des clés du cookie. Testez mauvais type, clé inconnue, dépassement et JSON invalide. Le refus ou le défaut prévu doit être explicite et ne doit pas devenir un privilège de repli. Cette conception traite à la fois les capacités du parseur et la confiance accordée aux données.
Points de vigilance : Le manuel déconseille les données non fiables même avec cette option ; elle n’assure pas la sûreté globale. Un format de données sans instanciation d’objets PHP réduit le risque ; validation et frontière de confiance restent nécessaires. Base64 est réversible et n’authentifie ni ne neutralise la structure sérialisée. Une exception n’annule pas nécessairement les effets déclenchés pendant une désérialisation.
Reference documentation ↗Identifiant PSP hors plage : conserver les chiffres comme chaîne
{"transactionId":12345678901234567890} Un identifiant peut ressembler à un nombre sans avoir de sens arithmétique. Si l’entier JSON dépasse PHP_INT_MAX, un décodage numérique ordinaire peut perdre la précision en passant par une représentation flottante. Cette perte peut faire rechercher ou rapprocher la mauvaise opération.
JSON_BIGINT_AS_STRING préserve la représentation de cet entier hors plage sous forme de chaîne ; JSON_THROW_ON_ERROR permet de traiter une syntaxe invalide par une exception explicite. Après parsing, vérifiez le schéma, le type attendu et les règles de format, puis conservez l’identifiant comme chaîne dans le stockage et les échanges PHP/Java.
Ne convertissez pas ensuite en float pour normaliser, trier ou exporter. Un test doit vérifier l’égalité exacte de tous les chiffres après décodage, persistance et sérialisation. Ajoutez une valeur plus petite et une entrée malformée. Le flag de parsing protège cette représentation, mais ne donne aucune autorisation d’accès à l’opération identifiée.
Points de vigilance : Le flag préserve cet entier hors plage sous forme de chaîne ; le schéma doit ensuite être contrôlé. Le float peut déjà avoir perdu des chiffres avant la conversion en chaîne. L’identifiant dépasse la plage de int ; le cast ne garantit pas sa fidélité. JSON_THROW_ON_ERROR signale des erreurs de décodage, pas cette perte de précision autorisée.
Reference documentation ↗Worked example
<?php
declare(strict_types=1);
try {
$data = json_decode('{bad json}', true, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $error) {
echo 'Format JSON invalide';
}Le JSON invalide provoque JsonException. Le gestionnaire peut traduire cette erreur en réponse client sans exposer une trace interne.
Practical exercise
Parsez un document JSON de réservation et refusez un objet sans quantity, un grand identifiant numérique et un document mal formé.
View a suggested solution
Utilisez JSON_THROW_ON_ERROR et JSON_BIGINT_AS_STRING, puis vérifiez le schéma. Séparez erreur de décodage et erreur métier. Un identifiant opaque ne doit pas subir de conversion numérique ultérieure.
Verification checklist
- Ne pas avaler toutes les erreurs silencieusement.
- Fermer les ressources avec finally.
- Tester fuseaux et entrées mal formées.
Knowledge check
Related lesson: Erreurs, fichiers, dates et formats de données ↗Module validation
101 questions, local practice target of 75%. Suggested duration of 150 minutes, with no enforced deadline. Questions and choices are shuffled; corrections appear after submission. The quick lesson check and the final course exam remain separate exercises.
Start or resume the 101 questions →This records your own progress and does not certify mastery. Complete the exercise before moving on.
