Rien que cette semaine, j’ai par trois fois répondu à un client en lui disant que la fonctionnalité demandée n’était pas possible (ou du moins pas possible facilement ou sans pirouette technique) simplement parce qu’il manquait une ligne de code dans l’extension qu’il me demandait d’étendre.

Une seule ligne. Un seul hook pour pouvoir faire mon travail proprement.

Pas question de modifier le code de l’extension. A la prochaine mise à jour de cette dernière, mes modifications seraient ecrasées. D’ailleurs, si vous faites ça, arrêtez. Sérieusement. Modifier le code d’une extension (ou pire, du coeur de WordPress) et bloquer les mises à jour n’est pas une bonne solution.

Le pire c’est que cette ligne de code est vraiment simple et ne coûte absolument rien. En aucun cas cette ligne ne viendra perturber le fonctionnement de l’extension. Toute seule, elle ne fait rien. Mais si elle est là, alors vous facilitez la vie de tous les développeurs qui souhaitent étendre ou modifier le comportement de l’extension, y compris la vôtre !

Dans cet article, je vais râler un peu, et après on va voir comment ajouter des hooks dans vos développements pour simplifier la vie des développeurs (vous y compris).

Le problème

WordPress est, de base, un bon programme. Avec une installation nue de WordPress, vous pouvez déjà commencer à publier du contenu, dans un environnement facile à manipuler et sécurisé.

Vous pouvez publier vos articles, vos pages, offrir à vos utilisateurs la possibilité de commenter, une fonctionnalité de recherche, une navigation simplifiée à l’aide du système de taxonomies, des pages d’archives, etc…

Mais ce qui attire le plus dans WordPress, c’est sa modularité. Grâce au système d’extensions, vous pouvez étendre les fonctionnalités de WordPress et en faire presque ce que vous voulez. Presque.

Ce système d’extensions n’est possible que grâce aux fameux hooks de WordPress. D’ailleurs, l’ensemble de fonctions relative aux hooks est appelé la Plugin API, ce n’est pas pour rien.

C’est donc grâce aux multiples hooks présents dans le cœur de WordPress que les extensions fonctionnent. Les extensions se greffent sur ces hooks pour exécuter leur code et modifier le comportement ou les données de WordPress.

Les extensions vont donc vous permettre par exemple d’ajouter des fonctionnalités e-commerce à votre site, de renforcer sa sécurité ou encore d’ajouter des champs spéciaux supplémentaires pour vos publications.

Mais il est assez rare qu’une extension fasse exactement tout ce dont vous avez besoin. Il y a toujours quelque chose qui cloche, qui ne fonctionne pas comme prévu ou qui manque pour que ce soit “parfait”.

Les développeurs d’extensions font leur maximum pour répondre aux besoins courants de leurs utilisateurs, mais parfois, ce n’est pas suffisant, car votre besoin est spécifique. Votre site est unique, votre business est unique et votre besoin aussi.

Donc, vous appelez un développeur pour savoir s’il est possible d’ajouter la fonctionnalité souhaitée à l’extension. Et il va probablement devoir faire une extension pour cette extension.

Vous voyez où je veux en venir je pense.

Bonjour M Dupont,

Je suis désolé, je ne peux pas faire ce que vous demandez. J’ai lu son code et l’extension UnicornPluginForRankingOnGoogleUltimate ne permet pas de modifier la méta-description des pages de façon dynamique. Je ne peux pas la changer en fonction du signe astrologique du visiteur. Il manque une seule ligne de code qui me permettrait de le faire.

Vincent Dubroeucq

Si l’extension à étendre ne contient pas de hooks, elle ne permet pas de se greffer sur son comportement, donc vous ne pourrez pas lui ajouter de fonctionnalités proprement, façon WordPress. Vous ne pourrez donc pas faire votre travail, tout simplement.

La solution

Dans les trois cas que j’ai rencontrés rien que cette semaine, j’ai simplement envoyé un mail au développeur de l’extension en lui exposant mon souci, et en lui demandant s’il était possible d’ajouter un hook à un endroit précis, dans une fonction précise. Je lui ai donné le fichier, le numéro de ligne et lui ai même suggéré un nom de hook qui correspondait à leur façon de nommer leur fonctions ou les autres hooks, et ses paramètres.

Ensuite, il faut attendre un peu. Dans 95% des cas, si votre demande est raisonnable, ils seront contents de le faire. Ajouter un hook ne leur coûte absolument rien et ouvre des possibilités, aussi bien pour vous que pour eux.

Donc, si vous développez vous-même des extensions ou thèmes, ajoutez des hooks dans vos développements.

C’est facile et c’est essentiel pour qu’un utilisateur de votre thème ou extension puisse ajuster le comportement de votre extension pour ses besoins spécifiques.

Votre extension ou thème profite bien des hooks de WordPress pour se greffer dessus et modifier son comportement, pourquoi ne pas permettre à d’autres extensions de faire de même sur elle ?

Un exemple

Prenons un exemple bidon, mais plus concret.

Imaginons que vous développiez une extension qui permet d’imprimer des publications, et qui propose plusieurs formats d’impression: A4, A5, LetterUS, etc…

Dans l’administration de WordPress, vous avez pensé à tout (presque) et vous avez ajouté un champ <select> dans votre page de réglages pour choisir un format par défaut.

<select name="print-format">
    <option value=""><?php esc_html_e( 'None', 'example' ); ?></option>
    <option value="A4"><?php esc_html_e( 'A4', 'example' ); ?></option>
    <option value="A5"><?php esc_html_e( 'A5', 'example' ); ?></option>
    <option value="letter"><?php esc_html_e( 'Letter', 'example' ); ?></option>
</select>

Ouille. Alors bonne nouvelle, vous avez utilisé une chaine traduisible pour le label des options, donc on peut contribuer à votre extension en la traduisant (sujet d’une autre rant), mais tout votre <select> est en dur. Impossible d’interagir avec son affichage, impossible d’ajouter un format.

$formats = example_get_formats();
?>
<select name="print-format">
    <option value=""><?php esc_html_e( 'None', 'example' ) ?></option>
    <?php foreach ($formats as $value => $label) : ?>
        <option value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $label ); ?></option>
    <?php endforeach; ?>
</select>

<?php
// dans functions.php, par exemple
function example_get_formats(){
    $formats = array(
        'A4'     => __( 'A4', 'example' ),
        'A5'     => __( 'A5', 'example' ),
        'letter' => __( 'Letter', 'example' ),
    );
    return $formats;
}

C’est déjà mieux codé, car on dispose d’une fonction qui va nous retourner la liste des formats disponibles, que vous allez pouvoir réutiliser ailleurs, mais on ne peut toujours pas en ajouter.

<?php
// dans functions.php
function example_get_formats(){
    $formats = array(
        'A4'     => __( 'A4', 'example' ),
        'A5'     => __( 'A5', 'example' ),
        'letter' => __( 'Letter', 'example' ),
    );
    $formats = apply_filters( 'example_formats', $formats );
    return $formats;
}

En ajoutant $formats = apply_filters( 'example_formats', $formats );, vous laissez la possibilité à un autre développeur (ou vous-même !) de modifier la liste des formats disponibles, et d’en ajouter ou supprimer selon le contexte. Vous pouvez même mettre l’expression directement dans le return : return apply_filters( 'example_formats', $formats );

C’était facile, non ? Une seule ligne, qui ne change rien si aucune fonction ne se hooke dessus. Rien du tout. C’est gratuit !

apply_filters() et do_action()

apply_filters( $hook, ...$args ) va appliquer les filtres (= les fonctions) hookées sur $hook en leur passant les arguments $args.

Donc pour ajouter un format, on va enregistrer une fonction sur notre hook example_formats. Pour ça, on utilise add_filter().

add_filter( 'example_formats', 'my_formats', 10, 1 );
function my_formats( $formats ){
    $formats['A6'] = __( 'A6', 'my-domain' );
    return $formats; // Très important de retourner la donnée !
}

Avec add_filter( $hook, $function, $priority, $nb_args ) on enregistre une fonction $function pour s’exécuter sur $hook à la priorité $priority (par défaut 10), et cette fonction va recevoir $nb_args arguments (par défaut 1).

La ligne $formats = apply_filters( 'example_formats', $formats ); nous dit que la fonction hookée va recevoir $formats, et que le retour de la fonction va être stocké dans $formats, donc il ne faut pas oublier de retourner les formats dans le filtre !

do_action( $hook, ...$arg ) fonctionne de la même manière. Elle exécute les actions (= les fonctions) hookées sur $hook, en leur passant les arguments $args. La différence est qu’une action ne nécessite pas forcément de retourner une valeur, alors qu’un filtre oui, car on nous prête une valeur pour la manipuler. Il faut donc la retourner.

Dans notre exemple d’extension imaginaire, vous pouvez laisser des développeurs se greffer sur le processus d’impression ou autre en ajoutant des do_action à certains moments clés. Vous pouvez même en ajouter dans vos templates HTML, pour pouvoir ajouter des éléments.

TLDR

Ajoutez des hooks dans votre code. Un hook, c’est une seule ligne de code ! Un seul appel à apply_filters() ou do_action(). C’est tout ! C’est facile et cela n’a aucun impact sur les performances ou le fonctionnement de l’extension ou du thème.

Cela va permettre à d’autres développeurs de se greffer sur votre extension ou thème pour en modifier le comportement.

En plus, cela va vous permettre de proposer des extensions pour votre propre extension ! Comme WooCommerce et de nombreuses autres extensions gratuites ou payantes.

Vous éviterez les mails des développeurs pas contents parce qu’ils ne peuvent pas faire leur travail !

Concrètement, il suffit d’ajouter des apply_filters() à vos fonctions qui retournent des données sur lesquelles ont pourrait avoir besoin d’avoir la main, et d’ajouter des do_action() à vos fonctions qui font du traitement plus ou moins complexe ou à vos templates HTML.

C’est facile ! Et vous n’avez aucune raison de ne pas le faire !

Si apprendre à développer un thème pour WordPress proprement vous intéresse, vous pouvez jeter un œil à Développer son thème WordPress pour apprendre à organiser vos fichiers, et coder votre thème de façon simple mais efficace et intégrant toutes les bonnes pratiques de développement de thème. Y compris l’ajout de hooks !