« Cette valeur doit implémenter à la fois Lisible et Journalisable » : un commentaire PHPDoc peut le dire, mais rien n’empêche d’appeler la fonction avec un objet qui n’en respecte qu’une seule. Avant PHP 8.1, exprimer cette double contrainte dans la signature elle-même n’était tout simplement pas possible avec le système de types natif.
Les intersection types, disponibles depuis PHP 8.1, comblent ce vide : ils permettent de déclarer qu’un argument doit satisfaire plusieurs interfaces simultanément, et PHP applique cette vérification au moment de l’appel, sans attendre une erreur plus tard dans l’exécution.
Le problème concret avec une source de Block Bindings
Une source personnalisée de Block Bindings s’enregistre via register_block_bindings_source(), avec un rappel qui reçoit les arguments de la liaison et retourne une valeur à injecter dans l’attribut du bloc. Sur un projet qui centralise plusieurs sources autour d’un même magasin de données, il devient utile de faire transiter ce magasin sous forme d’objet, plutôt que de multiplier les appels de fonctions globales.
Si ce magasin doit à la fois exposer une méthode de lecture (une interface Lisible) et une méthode de journalisation des accès (une interface Journalisable), la fonction qui le consomme a besoin des deux contrats en même temps — ni l’un seul, ni une classe concrète figée qui empêcherait de substituer une autre implémentation en test.
Écrire l’intersection type
La syntaxe utilise le symbole & entre les noms d’interfaces, à la place du type habituel :

interface Lisible {
public function lire( string $cle ): mixed;
}
interface Journalisable {
public function journaliser( string $evenement ): void;
}
function valeur_depuis_magasin( Lisible&Journalisable $magasin, string $cle ): mixed {
$magasin->journaliser( 'lecture:' . $cle );
return $magasin->lire( $cle );
}
N’importe quelle classe qui implémente les deux interfaces peut être passée à cette fonction. Si une classe n’en implémente qu’une, PHP lève une TypeError dès l’appel, avant même d’entrer dans le corps de la fonction — une vérification qui, sans intersection type, n’aurait été possible qu’à la main, avec des appels à instanceof répétés.
Brancher cela sur l’enregistrement de la source
Le rappel attendu par register_block_bindings_source() peut s’appuyer sur une méthode qui, elle-même, exige cette double interface :
function get_source_value( array $source_args, $block_instance ): mixed {
$magasin = mon_projet_recuperer_magasin(); // renvoie Lisible&Journalisable
return valeur_depuis_magasin( $magasin, $source_args['cle'] ?? '' );
}
register_block_bindings_source( 'mon-projet/magasin', array(
'label' => __( 'Magasin de données du projet', 'mon-projet' ),
'get_value_callback' => 'get_source_value',
) );
Cette organisation isole la contrainte de typage dans une fonction intermédiaire, ce qui garde le rappel enregistré auprès de WordPress simple, tout en profitant de la vérification stricte plus bas dans la chaîne d’appel.
Ce que les intersection types ne remplacent pas
Ils ne remplacent pas les union types (introduits en PHP 8.0), qui expriment l’inverse — « l’un ou l’autre » plutôt que « les deux à la fois ». Les deux mécanismes répondent à des besoins différents et ne sont pas interchangeables : une union type élargit ce qu’une fonction accepte, une intersection type le restreint à l’intersection de plusieurs contrats.
- Union type :
Lisible|Journalisable— accepte l’un ou l’autre, ou les deux. - Intersection type :
Lisible&Journalisable— exige impérativement les deux à la fois.
Prérequis à vérifier avant d’adopter la syntaxe
Les intersection types demandent PHP 8.1 au minimum. Sur un projet qui doit encore prendre en charge une version antérieure de PHP pour des raisons d’hébergement, cette syntaxe provoquera une erreur d’analyse pure et simple, avant même l’exécution. Un contrôle de la version minimale déclarée dans l’en-tête du thème ou de l’extension, couplé à une vérification réelle sur l’environnement de production visé, évite ce genre de mauvaise surprise en déploiement.
Sur les sources de Block Bindings qui manipulent un état partagé, la règle qu’on retient : dès que deux comportements distincts sont attendus d’un même objet, deux interfaces valent mieux qu’une classe abstraite unique — et l’intersection type documente ce choix directement dans la signature.
En résumé
Les intersection types de PHP 8.1 offrent un moyen précis d’exprimer qu’un argument doit remplir plusieurs rôles à la fois, sans recourir à des vérifications manuelles répétées. Pour une source de Block Bindings qui s’appuie sur un objet partagé aux responsabilités multiples, cette syntaxe rend la contrainte visible dès la signature, plutôt que de la laisser dans un commentaire que personne ne relit.