Comprendre le mécanisme
Les PHPDocs peuvent exprimer unions, listes, tableaux de forme précise et contraintes utiles à l’analyse. Ces annotations décrivent un contrat ; elles ne transforment pas un corps HTTP en donnée valide. Écrire qu’un tableau contient amount positif ne rend pas vraie une entrée négative. Le code exécuté doit refuser les types, clés et valeurs non conformes avant de produire l’objet du domaine.
Raisonner et vérifier
Séparez parseur, validateur et modèle métier. Une garde valide d’abord la structure puis les invariants : entier n’implique pas montant autorisé, chaîne n’implique pas destination sûre. Préférez des DTO et objets de valeur pour éviter de disperser des tableaux aux clés approximatives. Les erreurs d’entrée doivent être testées sans convertir silencieusement toute valeur en type attendu.
Décrire puis établir
Un PHPDoc décrit un contrat. Une annotation n’exécute pas une garde d’entrée. Le commentaire array{amount: positive-int} n’exécute aucune vérification du JSON. Le code doit contrôler structure, type natif et bornes avant de transmettre la valeur à une fonction qui suppose ce contrat.
Understand this common mistake
Un PHPDoc valide automatiquement le JSON réseau.
Une annotation n’exécute pas une garde d’entrée.
Formes de tableau
Une forme de tableau précise ses clés attendues. Les données externes doivent établir ce contrat. Une array shape nomme les clés obligatoires et optionnelles. Testez clé manquante, clé présente avec null et valeur de mauvais type : ces situations ont des contrats distincts qu’un simple accès au tableau masque.
Understand this common mistake
Toute array shape garantit la présence réelle de ses clés sans contrôle.
Les données externes doivent établir ce contrat.
Unions
Une union indique plusieurs types possibles. Une opération doit être compatible avec les possibilités restantes. Un retour User|null demande de gérer l’absence avant d’appeler une méthode utilisateur. Les unions documentent plusieurs chemins ; elles ne signifient pas que l’appelant peut choisir arbitrairement celui qui l’arrange.
Understand this common mistake
Une union autorise toute méthode de l’un de ses membres.
Une opération doit être compatible avec les possibilités restantes.
Type et domaine
Une garde peut vérifier type et valeur. La positivité est un invariant supplémentaire. is_int puis une comparaison positive rejettent la chaîne '12'. Ajoutez un plafond et une règle de devise pour un montant ; les types raffinés ne doivent pas dépasser ce que la garde établit.
Understand this common mistake
is_int garantit que tout montant est positif.
La positivité est un invariant supplémentaire.
Conversions destructrices
Un cast peut masquer une entrée incorrecte. La conversion ne remplace pas une politique d’acceptation. Caster 'inconnu' en entier peut produire zéro et perdre l’erreur initiale. Définissez les représentations admises puis convertissez après validation, en vérifiant dépassement et conservation de la précision.
Understand this common mistake
Caster toute entrée en int vérifie la grammaire métier.
La conversion ne remplace pas une politique d’acceptation.
DTO validé
Un DTO peut structurer des données validées. La permission demeure une décision distincte. Construisez un objet d’entrée seulement après validation, ou faites refuser son constructeur en cas d’invariant violé. Un nom comme ValidPayment ne rend pas sûr un constructeur qui accepte toute donnée sans contrôle.
Understand this common mistake
Construire un DTO prouve automatiquement l’autorisation.
La permission demeure une décision distincte.
Plafond métier
Un entier positif peut dépasser un plafond métier. Les limites du domaine peuvent être plus étroites. Un positive-int de plusieurs milliards peut être incompatible avec un remboursement de dix euros. Vérifiez solde, autorisation et limites en contexte ; la propriété arithmétique positive reste une seule condition parmi plusieurs.
Understand this common mistake
positive-int suffit à autoriser tout montant.
Les limites du domaine peuvent être plus étroites.
Matrice de refus
Les erreurs de frontière doivent être testées. Les absences et mauvais types doivent être refusés selon le contrat. Envoyez tableaux, flottants, chaînes numériques, négatifs et valeurs extrêmes. Vérifiez l’erreur publique et l’absence d’écriture, pas seulement que PHPStan continue d’inférer int à la sortie nominale.
Understand this common mistake
Seul un exemple nominal prouve toute validation.
Les absences et mauvais types doivent être refusés selon le contrat.
Parsing distinct
Le parsing et la validation sont des étapes différentes. Structure et invariants peuvent encore être invalides. json_decode peut produire un tableau valide syntaxiquement qui ne contient pas les champs requis. Une exception de parsing et une violation de schéma doivent être traitées comme deux causes différentes.
Understand this common mistake
Un JSON syntaxiquement correct est toujours conforme au domaine.
Structure et invariants peuvent encore être invalides.
Politique de conversion
Un contrat doit définir les conversions acceptées. L’API choisit explicitement sa grammaire d’entrée. Une API peut accepter une chaîne décimale par contrat explicite ; une autre exige un entier JSON. Documentez ce choix et évitez qu’un cast opportuniste élargisse silencieusement les entrées acceptées.
Understand this common mistake
La chaîne numérique doit toujours être acceptée comme entier dans toute API.
L’API choisit explicitement sa grammaire d’entrée.
Atelier guidé : lire, expliquer et vérifier le code
<?php
declare(strict_types=1);
function accept(mixed $value): bool {
return is_int($value) && $value > 0;
}
echo accept('12') ? 'accepted' : 'rejected'; Évaluez is_int avant la comparaison numérique : la valeur fournie est une chaîne et échoue donc à la première condition. Comparez ensuite avec un entier positif, zéro et un tableau. Pour transformer cet exemple en frontière de paiement, ajoutez un plafond métier et les contrôles d’autorisation nécessaires.
Le résultat affiché est un libellé. La fonction est syntaxiquement valide. La garde demande un int ; la valeur reçue est une string. Le contrat ne prévoit pas ici de conversion de chaîne.
Travail pratique : Envoyez 12, "12", 0, -1 et null à la frontière de laboratoire. Comparez un cast aveugle avec la garde.
Critères de correction : Seul l’entier positif respecte ce contrat strict. Vérifiez ensuite la limite métier et la permission séparément. Une API acceptant aussi une chaîne doit définir explicitement sa grammaire de conversion.
Worked example
<?php
declare(strict_types=1);
function positiveAmount(mixed $value): int
{
if (!is_int($value) || $value <= 0) {
throw new InvalidArgumentException('Montant invalide');
}
return $value;
}La garde vérifie type et valeur ; elle ne décide pas si un utilisateur peut payer ce montant.
Practical exercise
Envoyez 12, "12", 0, -1 et null à la frontière de laboratoire. Comparez un cast aveugle avec la garde.
View a suggested solution
Seul l’entier positif respecte ce contrat strict. Vérifiez ensuite la limite métier et la permission séparément. Une API acceptant aussi une chaîne doit définir explicitement sa grammaire de conversion.
Verification checklist
- Annotations honnêtes.
- Gardes exécutées.
- Invariants distincts des types.
Knowledge check
Related lesson: 03. Types riches et validation des frontières ↗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.
