Le WordPress d'aujourd'hui, décodé pour les développeurs

Extensions

spl_object_id() distingue deux instances d’une classe dans un tableau de hooks

Pour les développeurs d'extensions qui gèrent plusieurs instances d'une même classe accrochées à des hooks, un identifiant unique évite les confusions.

Par WordPress Développement • 24 septembre 2022 • 4 min de lecture • Aucun commentaire
spl_object_id() distingue deux instances d'une classe dans un tableau de hooks

spl_object_id( $instance ) retourne un entier unique attribué à chaque objet PHP tant qu’il existe en mémoire. Cette fonction, disponible depuis PHP 7.2, résout un problème précis et récurrent dans une architecture orientée objet qui attache plusieurs instances d’une même classe à des hooks distincts : comment s’assurer qu’on retire, plus tard, exactement la bonne instance, et pas une autre créée entre-temps ?

Quand une classe de service est instanciée plusieurs fois — par exemple, une classe générique de synchronisation configurée différemment pour plusieurs points de terminaison —, chaque instance peut s’accrocher à un hook avec une méthode de rappel identique par son nom, mais appartenant à un objet différent. Retirer un hook avec remove_action() exige de fournir exactement la même instance que celle utilisée lors de l’ajout : une instance différente, même de la même classe, avec les mêmes propriétés, ne sera jamais reconnue comme identique.

Le problème concret, illustré

class SynchroniseurExterne {
    public function __construct( private string $point_de_terminaison ) {}

    public function synchroniser() {
        // logique de synchronisation
    }
}

$synchro_a = new SynchroniseurExterne( 'commandes' );
$synchro_b = new SynchroniseurExterne( 'clients' );

add_action( 'mon_extension_tick', array( $synchro_a, 'synchroniser' ) );
add_action( 'mon_extension_tick', array( $synchro_b, 'synchroniser' ) );

Si, plus tard dans le code, il faut retirer uniquement le hook associé à $synchro_a sans toucher à $synchro_b, il est indispensable de conserver une référence exacte à la première instance. Sans un identifiant explicite pour retrouver laquelle est laquelle, une confusion s’installe rapidement dans un code qui gère plusieurs instances créées dynamiquement, par exemple à partir d’une boucle sur une liste de configurations.

L'essentiel à retenir : Deux instances d'une même classe ne sont pas interchangeables pour un hook ; spl_object_id() fournit un identifiant unique par instance, léger et rapide ; remove_action() exige la même instance exacte que celle utilisée à l'ajout

Utiliser spl_object_id() pour suivre chaque instance

class GestionnaireSynchroniseurs {
    private array $instances = array();

    public function enregistrer( SynchroniseurExterne $instance ): int {
        $identifiant = spl_object_id( $instance );
        $this->instances[ $identifiant ] = $instance;

        add_action( 'mon_extension_tick', array( $instance, 'synchroniser' ) );

        return $identifiant;
    }

    public function retirer( int $identifiant ): void {
        if ( isset( $this->instances[ $identifiant ] ) ) {
            remove_action(
                'mon_extension_tick',
                array( $this->instances[ $identifiant ], 'synchroniser' )
            );
            unset( $this->instances[ $identifiant ] );
        }
    }
}

Ce gestionnaire conserve une correspondance explicite entre un identifiant numérique léger et l’instance réelle, ce qui permet de retirer précisément un hook donné sans conserver de référence directe à l’objet dans le code appelant — utile notamment quand cet identifiant doit transiter par une file d’attente ou un tableau sérialisable.

spl_object_id() plutôt que spl_object_hash()

Avant PHP 7.2, la fonction spl_object_hash() remplissait un rôle proche, en retournant une chaîne de caractères plutôt qu’un entier. spl_object_id() est préférable depuis sa disponibilité : elle retourne un entier plus léger à manipuler et à comparer, sans les collisions théoriques, bien que rarissimes, associées à un hachage de chaîne.

Une limite importante à connaître

L’identifiant retourné par spl_object_id() peut être réattribué à un nouvel objet une fois l’objet original détruit et le garbage collector passé. Cela signifie qu’il ne faut jamais conserver un identifiant au-delà de la durée de vie réelle de l’objet concerné, ni s’en servir comme identifiant persistant en base de données : il n’a de sens que pendant l’exécution en cours, tant que l’objet original reste référencé quelque part en mémoire.

  • Utiliser spl_object_id() uniquement pour un suivi en mémoire, pendant une seule exécution PHP.
  • Ne jamais persister cet identifiant dans une option ou une table, il n’a aucune signification d’une exécution à l’autre.
  • Conserver l’instance elle-même dans un tableau interne, comme dans l’exemple, pour garantir sa disponibilité tant que nécessaire.

Une classe instanciée plusieurs fois n’est pas un détail d’implémentation anodin dès qu’elle s’accroche à des hooks : chaque instance mérite d’être identifiable individuellement, sans ambiguïté.

En résumé

spl_object_id() répond à un problème précis : distinguer, dans une architecture orientée objet, plusieurs instances d’une même classe accrochées séparément à des hooks WordPress. Un identifiant léger, valable uniquement pendant l’exécution en cours, suffit à retrouver et retirer précisément la bonne instance, sans confusion ni logique de comparaison approximative sur les propriétés de l’objet.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi