Comprendre le mécanisme
Les génériques exprimés en PHPDoc permettent de relier types d’entrée, de sortie et de collections. Une collection de Reservation peut ainsi garder son type au fil d’un repository sans retomber dans des tableaux non spécifiés. Cette information améliore la détection d’appels incohérents, mais ne prouve pas que les réservations appartiennent à l’utilisateur courant. Un paramètre de type n’exprime pas tout le contexte d’accès.
Raisonner et vérifier
N’élargissez pas un contrat uniquement pour faire disparaître un diagnostic. Vérifiez la variance et les capacités réellement promises par l’abstraction. Pour les données externes, construisez les objets après validation ; pour les objets persistés, appliquez les filtres et décisions de droits nécessaires. Une extension ou un stub doit décrire le comportement réel de la bibliothèque ciblée.
Relier entrée et sortie
Un paramètre T relie des types dans un contrat. Le générique décrit une relation pour l’analyse. Un paramètre T permet de dire que firstOrNull conserve le type des éléments reçus. Sans ce lien, retourner simplement mixed ferait perdre à chaque appelant la connaissance déjà disponible sur sa collection.
Erreur fréquente à comprendre
T chiffre la valeur de la collection.
Le générique décrit une relation pour l’analyse.
Listes indexées
list<T> décrit les éléments d’une liste. Le type ne donne pas une autorisation d’accès. list<T> décrit une suite à indices entiers contigus depuis zéro. Après une opération qui conserve des clés dispersées, réindexez seulement si cela correspond au contrat ; un tableau quelconque n’est pas nécessairement une liste.
Erreur fréquente à comprendre
list<T> prouve la propriété métier des éléments.
Le type ne donne pas une autorisation d’accès.
Absence explicite
Une sortie T ou null doit traiter null. La nullabilité reste dans le contrat. La liste vide produit null dans firstOrNull. L’appelant doit choisir un défaut, retourner une absence ou lever une erreur adaptée avant de traiter le résultat comme une instance certaine.
Erreur fréquente à comprendre
Le générique supprime automatiquement tous les cas vides.
La nullabilité reste dans le contrat.
Accès cohérents
Une collection typée réduit les accès incohérents. Les permissions ne dérivent pas du seul nom de classe. Une collection Reservation évite de supposer qu’un élément est un User. Ajoutez les méthodes nécessaires au contrat et laissez l’analyse repérer les appels incohérents sans recourir à des casts de confort.
Erreur fréquente à comprendre
Le nom Reservation accorde tous les droits de lecture.
Les permissions ne dérivent pas du seul nom de classe.
Variance et mutation
La variance doit respecter les capacités promises. Les entrées et sorties imposent des contraintes différentes. Une collection lisible d’un sous-type et une collection modifiable n’ont pas les mêmes possibilités de substitution. Si un appelant peut insérer un autre sous-type, la promesse faite au détenteur initial peut être violée.
Erreur fréquente à comprendre
Tout élargissement de type est compatible avec toute substitution.
Les entrées et sorties imposent des contraintes différentes.
Entrées externes
Les données externes doivent être validées avant construction du modèle. Le commentaire ne remplace pas le contrôle runtime. Une annotation list<Order> autour d’un JSON ne construit aucun Order. Parsez chaque élément et vérifiez sa structure avant de former une collection dont les méthodes supposent des objets valides.
Erreur fréquente à comprendre
Une annotation générique transforme toute entrée hostile en objet sûr.
Le commentaire ne remplace pas le contrôle runtime.
Stubs honnêtes
Un stub doit décrire le comportement réel. Une description fausse peut tromper l’analyse. Un stub de bibliothèque doit conserver null et les types d’erreur réellement possibles. Enlever une possibilité pour rendre l’analyse verte ne change pas le comportement du fournisseur exécuté en production.
Erreur fréquente à comprendre
Un stub peut inventer un retour pour faire taire toute erreur.
Une description fausse peut tromper l’analyse.
Périmètre du repository
Les repositories doivent conserver leurs règles de périmètre. Le filtre métier doit être implémenté. Un repository typé doit aussi filtrer le tenant ou appliquer la politique appropriée. La signature Order ne signifie pas Order autorisé pour cet acteur ; testez les identifiants d’un autre périmètre.
Erreur fréquente à comprendre
Un retour list<Reservation> filtre automatiquement le tenant.
Le filtre métier doit être implémenté.
Cas vide
Les tests doivent couvrir une liste vide. La non-vacuité demande une contrainte différente. Vérifiez une collection vide avant le scénario à plusieurs éléments. Ce cas expose le contrat nullable et les opérations qui supposent sans preuve un premier élément toujours présent.
Erreur fréquente à comprendre
Une liste typée est nécessairement non vide.
La non-vacuité demande une contrainte différente.
Abstraction précise
Une abstraction doit préciser les types d’éléments. Cela retire des informations utiles à l’analyse. Une interface de collection doit déclarer le type de ses valeurs et de ses clés lorsque ces deux informations comptent. Un simple iterable perd le lien qui rend les traitements suivants vérifiables.
Erreur fréquente à comprendre
Remplacer tous les éléments par mixed améliore toujours la précision.
Cela retire des informations utiles à l’analyse.
Atelier guidé : lire, expliquer et vérifier le code
<?php
declare(strict_types=1);
/** @template T
* @param list<T> $items
* @return T|null
*/
function firstOrNull(array $items): mixed {
return $items[0] ?? null;
}
$result = firstOrNull([]); Suivez le type T depuis le paramètre jusqu’au retour puis exécutez le cas de la liste vide. La présence de null dans la signature décrit un résultat réel. Proposez un traitement d’absence compatible avec le métier, sans remplacer la signature par une promesse artificiellement plus forte.
Le générique relie des types, pas les permissions. La sortie annonce l’absence et le code la produit ici. La fonction ne crée pas un élément. Le type list ne donne pas cette cardinalité minimale.
Travail pratique : Utilisez la fonction avec une liste d’objets puis une liste de chaînes. Analysez un appel de méthode sans garde du résultat.
Critères de correction : L’analyse doit conserver le type de chaque liste et signaler le cas nullable pertinent. Ajoutez une garde explicite ; vérifiez aussi les listes vides à l’exécution.
Exemple commenté
<?php
declare(strict_types=1);
/**
* @template T
* @param list<T> $items
* @return T|null
*/
function firstOrNull(array $items): mixed
{
return $items[0] ?? null;
}La relation T est conservée par l’analyse, tandis que null reste une issue possible.
Exercice de mise en pratique
Utilisez la fonction avec une liste d’objets puis une liste de chaînes. Analysez un appel de méthode sans garde du résultat.
Voir une proposition de correction
L’analyse doit conserver le type de chaque liste et signaler le cas nullable pertinent. Ajoutez une garde explicite ; vérifiez aussi les listes vides à l’exécution.
Points de vérification
- Relations de types conservées.
- Nullable traité.
- Droits hors du seul paramètre T.
Contrôle de connaissances
Cours associé : 04. Génériques, collections et contrats ↗Validation du module
101 questions, objectif pédagogique de 75 %. Durée conseillée de 150 minutes, sans limite imposée. Les questions et les choix sont mélangés ; le corrigé apparaît après validation. Le contrôle rapide de la leçon et l’examen final du cours restent des exercices distincts.
Commencer ou reprendre les 101 questions →Cette marque suit votre propre avancement ; elle ne certifie pas la maîtrise du sujet. Effectuez l’exercice avant de passer à la suite.
