$this->methode(...) : cette ligne suffit, depuis PHP 8.1, à remplacer un tableau de callback bâti à la main. Le changement paraît anodin, mais il élimine une source d’erreurs discrètes dans les filtres qui manipulent des attributs d’accessibilité, là où une faute de frappe dans une chaîne de caractères ne se voit qu’à l’exécution.
Ce tutoriel part d’un cas concret : un filtre maison qui ajoute des attributs aria-* au balisage d’un widget de recherche, enregistré jusque-là avec la syntaxe classique array( $this, 'nom_de_methode' ). L’objectif est de migrer proprement vers les first-class callable syntax sans rien casser côté rendu, ni toucher au typage des paramètres ou aux enums, qui sortent du périmètre de cet article.
Le filtre avant la migration
Le point de départ est une classe Widget_Recherche_Accessible qui enregistre un filtre pour injecter aria-label et aria-describedby sur le champ de recherche généré par le thème :
class Widget_Recherche_Accessible {
public function __construct() {
add_filter( 'wpm_widget_aria_attributes', array( $this, 'ajouter_attributs_aria' ), 10, 2 );
}
public function ajouter_attributs_aria( $attributs, $contexte ) {
$attributs['aria-label'] = 'Rechercher sur le site';
$attributs['aria-describedby'] = 'wpm-recherche-aide';
return $attributs;
}
}
Ce code fonctionne parfaitement. Mais la chaîne 'ajouter_attributs_aria' n’est reliée à rien tant que PHP ne l’exécute pas : un renommage de méthode oublié dans un IDE trop pressé, et le filtre disparaît silencieusement. Aucun message d’erreur, aucun warning — juste des attributs ARIA qui ne sont plus posés sur le champ de recherche.
Pourquoi passer aux first-class callables
La RFC acceptée pour PHP 8.1 introduit une notation qui transforme n’importe quel appel de fonction ou de méthode en objet Closure, simplement en remplaçant les arguments par .... Trois bénéfices se dégagent particulièrement pour du code lié à l’accessibilité, où la fiabilité du câblage compte autant que le contenu généré :
- Un outil comme PHPStan ou Psalm détecte immédiatement une méthode renommée, alors qu’un tableau de callback reste invisible pour l’analyse statique.
- Le renommage automatique d’un IDE moderne suit la référence, ce qui n’est jamais le cas avec une chaîne de caractères.
- La lecture du code gagne en clarté : on voit tout de suite qu’il s’agit d’une méthode d’instance, sans avoir à interpréter un tableau à deux éléments.

Étape 1 : repérer les callables invoqués par chaîne
Avant de modifier quoi que ce soit, il faut lister les points d’enregistrement concernés. Une recherche simple dans le dossier du plugin ou du thème permet de retrouver les occurrences :
grep -rn "array( \$this," inc/ --include="*.php"
Pour ce widget, deux lignes ressortent : l’enregistrement du filtre wpm_widget_aria_attributes dans le constructeur, et un second callback attaché à l’action wp_footer pour injecter un script de repli en l’absence de JavaScript.
Étape 2 : remplacer par la syntaxe first-class
La conversion est directe : on retire le tableau et les guillemets, on ajoute les parenthèses vides.
class Widget_Recherche_Accessible {
public function __construct() {
add_filter( 'wpm_widget_aria_attributes', $this->ajouter_attributs_aria(...), 10, 2 );
add_action( 'wp_footer', $this->injecter_repli_js(...) );
}
public function ajouter_attributs_aria( $attributs, $contexte ) {
$attributs['aria-label'] = 'Rechercher sur le site';
$attributs['aria-describedby'] = 'wpm-recherche-aide';
return $attributs;
}
public function injecter_repli_js() {
echo '<script>document.documentElement.classList.add("js-actif");</script>';
}
}
Un détail à surveiller : la syntaxe (...) capture la visibilité au moment de l’appel, pas au moment de la définition. Une méthode private appelée depuis l’extérieur de la classe continuera donc de lever une erreur de visibilité, exactement comme avant. Rien ne change de ce côté-là.
Étape 3 : vérifier la compatibilité avec les hooks WordPress
Les fonctions add_filter() et add_action() acceptent tout type callable, et un objet Closure issu d’un first-class callable en fait pleinement partie. Aucune adaptation n’est nécessaire côté API des hooks. Il reste toutefois un point à vérifier avec soin : si le code appelle ensuite remove_filter() sur ce même hook, il doit désormais utiliser une référence strictement identique au callable enregistré, ce qui suppose de conserver la closure dans une propriété si un retrait ultérieur est prévu.
class Widget_Recherche_Accessible {
private \Closure $callback_aria;
public function __construct() {
$this->callback_aria = $this->ajouter_attributs_aria(...);
add_filter( 'wpm_widget_aria_attributes', $this->callback_aria, 10, 2 );
}
public function desactiver() {
remove_filter( 'wpm_widget_aria_attributes', $this->callback_aria, 10 );
}
}
Conseil maison : sur un plugin où plusieurs classes enregistrent des filtres liés à l’accessibilité, garder une convention unique — soit tout en first-class callables, soit tout en tableaux — évite les revues de code où l’on hésite sur la raison d’un choix ponctuel.
En résumé
La migration vers les first-class callables ne change rien au comportement du filtre wpm_widget_aria_attributes : les attributs ARIA continuent d’être posés exactement de la même façon sur le champ de recherche. Ce qui change, c’est la robustesse du câblage : un renommage de méthode devient une erreur détectée à l’analyse statique plutôt qu’un silence en production. Pour un projet qui accumule des filtres d’accessibilité au fil des widgets, ce gain de fiabilité justifie à lui seul la mise à jour, indépendamment du typage strict ou des enums que PHP 8.1 introduit par ailleurs.