Écrire des plugins extensibles avec des actions et des filtres

Une des nombreuses choses que vous trouverez lors de l’examen du code source d’un bon développeur de plug-in sont les crochets et filtres personnalisés que le développeur a placés tout au long du plug-in. La présence de ces crochets et filtres d'action rend le plugin "extensible", ce qui signifie que d'autres plugins et thèmes peuvent manipuler ou ajouter le comportement du plugin..

L'écriture de plugins extensibles est quelque chose que je vous encourage fortement à faire. Il ya un lot de bonnes raisons pour lesquelles vous devriez le faire, mais très peu (le cas échéant) de raisons pour lesquelles vous devriez éviter cette pratique.

Nous allons examiner plusieurs éléments de plugins extensibles:

  • Une explication de ce que sont les plugins extensibles
  • Raisons pour lesquelles vous devriez écrire des plugins extensibles
  • Les outils de base dont vous avez besoin
  • Comment vous devez écrire vos plugins pour les rendre extensibles
  • Exemples simples de points d'ancrage et de filtres pour illustrer leur utilisation

Une remarque importante: ce tutoriel utilisera des techniques de programmation purement procédurales. Tout ce dont je parle ici s'applique toujours lors de l'utilisation de la programmation orientée objet (OOP), mais il est plus simple d'apprendre d'abord ces techniques dans un contexte procédural..


Qu'est-ce qu'un plugin extensible?

Un plugin extensible est un plugin qui peut être modifié et étendu au-delà de son objectif initial par un autre plugin ou thème. Lorsqu'un plugin est extensible, d'autres plugins (ou thèmes) peuvent modifier le comportement ou la sortie du plugin. Par exemple, les plug-ins de commerce électronique permettent aux passerelles de paiement supplémentaires qui permettent de traiter les achats via des systèmes de paiement supplémentaires. Ces passerelles de paiement sont des plugins distincts qui se connectent simplement au plugin principal et étendent ses fonctionnalités..

N'importe quel plugin peut être extensible, bien que seule une petite minorité de plugins publiés le soit. Pour être extensible, ou modulaire (un autre terme pour la même chose), le développeur d'un plugin doit prendre une décision consciente en procédant de cette façon en implémentant les éléments nécessaires permettant à d'autres plugins et thèmes de se lier au noyau du plugin. comportement.


Pourquoi écrire des plugins extensibles??

Il y a beaucoup de bonnes raisons d'écrire des plugins extensibles, mais l'une des raisons principales est qu'il n'y en a tout simplement pas. ne pas pour écrire vos plugins de cette façon, surtout pas lorsque vos plugins sont publiés dans la communauté WordPress, que ce soit en plugins gratuits ou payants.

Lorsque vous écrivez des plug-ins extensibles, vous permettez à d'autres développeurs d'étendre votre plug-in et de le rendre encore meilleur, mais sans jamais changer le code source principal. Vous aidez également considérablement les développeurs et les utilisateurs à adapter le plug-in à leurs besoins. Laissez-moi vous donner un exemple: dans mon plugin Easy Digital Downloads, il existe un système de code de réduction. Les codes de réduction sont limités à une seule utilisation par utilisateur. Par conséquent, si un utilisateur tente d'appliquer la même réduction sur deux achats différents, il recevra une erreur. Une de mes utilisatrices du monde réel a constaté qu'elle ne souhaitait pas limiter les remises à une seule utilisation par utilisateur. Je lui ai donc donné une fonction simple qu'elle a insérée dans un nouveau plugin personnalisé et la restriction a été supprimée, sans toucher au code du plugin principal..

Le code extensible rend également les autres développeurs extrêmement heureux quand ils le trouvent, car leur travail d'adaptation du code est devenu beaucoup plus facile..


Les outils / fonctions de base

Il existe plusieurs outils clés dont vous avez besoin pour écrire des plugins extensibles. Si vous avez écrit des plugins ou des thèmes avant de lire ceci, vous connaissez probablement au moins un peu ces fonctions, même si c'est uniquement parce que vous les avez vues utilisées.

Avant de vous montrer les fonctions que vous allez utiliser, parlons d’abord de deux concepts principaux: crochets et filtres.

Un hook d'action est un endroit dans votre plugin qui peut être "accroché" par des fonctions (à la fois dans votre plugin et d'autres plugins) afin que leur code soit exécuté à ce moment-là. Lorsqu’un hook d’action est exécuté, toutes les fonctions qui lui sont connectées ou "accrochées" s’exécutent également..

Un crochet de filtre est également un endroit dans votre plugin pour associer d'autres fonctions, mais elles fonctionnent légèrement différemment des actions. Les filtres permettent aux données d'être manipulées ou modifiées avant leur utilisation.

La principale différence entre les actions et les filtres réside dans le fait que les actions sont généralement utilisées pour exécuter des fonctions et les filtres pour manipuler des données..

À moins que vous ne soyez déjà très familiarisé avec les actions et les filtres, je vous encourage fortement à lire les notes du Codex qui les concernent..

Pour les actions, il y a quatre fonctions principales:

  • do_action () - cela définit un emplacement d'accrochage pour les actions
  • add_action () - cela attache une fonction à un crochet créé avec do_action ()
  • has_action () - cela vérifie si une action a été enregistrée avec do_action ()
  • remove_action () - cela supprime une action qui a été définie avec add_action ()

De ces quatre, vous utiliserez do_action () et add_action () le plus.

Pour les filtres, il existe également quatre fonctions principales:

  • apply_filters () - cela crée un emplacement d'accroche pour les filtres personnalisés à lier dans
  • add_filter () - cela attache un filtre personnalisé à un crochet créé avec apply_filters ()
  • has_filter () - cela vérifie si un filtre a été enregistré avec apply_filters ()
  • remove_filter () - cela supprime un filtre précédemment connecté à apply_filters ()

Comme pour les actions, apply_filters () et add_filter () sont les deux que vous utiliserez le plus.

Si vous êtes confus à ce stade, ne vous inquiétez pas, nous allons voir comment les utiliser dans la section suivante..


Implémentation dans vos propres plugins

Afin de rendre votre plugin vraiment extensible, vous devez utiliser les fonctions de clé mentionnées ci-dessus dans l'ensemble du plugin. Au début, vous trouverez peut-être difficile, lourd, ennuyeux ou de nombreux autres adjectifs applicables de placer constamment ces fonctions supplémentaires dans votre code, en particulier lorsque vous ne voyez aucun avantage immédiat ou que vous ne les utilisez pas..

Ce que vous constaterez cependant, c'est qu'une fois que vous aurez l'habitude d'écrire vos plugins avec toutes ces fonctions en tête, il deviendra une seconde nature de les inclure..

Il existe quelques scénarios principaux dans lesquels vous utiliserez des filtres dans vos plugins:

  • Lorsque les tableaux sont configurés. Des filtres seront ajoutés ici afin que d'autres plugins puissent modifier les données avant leur utilisation..
  • Lorsque les objets de données sont configurés. Comme avec les tableaux, vous utiliserez un filtre sur les objets afin que les autres développeurs puissent modifier l'objet avant qu'il ne soit utilisé..
  • Lorsque les chaînes de données sont configurées. Avec un filtre disponible sur une chaîne, les autres développeurs peuvent modifier la chaîne entière, en modifier certaines parties ou y ajouter des éléments..

Parmi les scénarios ci-dessus, il est plus courant d'utiliser des filtres lorsque les données sont renvoyées ou juste avant leur utilisation. Par exemple, si vous avez un plug-in qui effectue une requête posts, il est préférable de transmettre le tableau des arguments de requête via un filtre avant de les transmettre à get_posts () ou WP_Query afin que d'autres puissent manipuler la requête avant qu'elle ne soit faite.

En ce qui concerne les actions, il existe également plusieurs instances principales où vous les placerez:

  • Avant qu'une tâche soit exécutée.
  • Après qu'une tâche est exécutée.
  • Dans votre marquage pour permettre l'insertion de balises supplémentaires.

Considérons quelques exemples maintenant.

1. Afficher du HTML avec un shortcode

Les codes courts générés en HTML sont extrêmement courants (en fait, ils sont probablement les plus courants), et l’un des moyens de rendre les codes courts de notre plugin plus conviviaux pour les autres développeurs est de leur fournir un moyen de modifier le contenu du code. shortcode, mais sans exiger qu'il soit désenregistré et réenregistré.

Tous les codes courts renvoient au lieu de refléter leur contenu, ce qui signifie que les données envoyées à l'écran seront sous la forme d'une chaîne avant d'être renvoyées. La totalité de la sortie HTML se présentant sous la forme d'une chaîne, vous pouvez la transmettre à travers un filtre avant de la renvoyer. Cela permettra aux autres développeurs de modifier le code HTML de votre shortcode..

Un développeur peut vouloir ajouter du balisage supplémentaire avant et après le code HTML par défaut: avec le filtre en place, il peut le faire..

Votre shortcode peut ressembler à quelque chose comme ceci:

 function wptp_sample_shortcode (atts, $ content = null) $ html = '
'; $ html. = '

Contenu de l'exemple de shortcode

'; $ html. = '
'; return $ html;

Nous pouvons améliorer cela en ajoutant un filtre à la déclaration, comme ceci:

 function wptp_sample_shortcode (atts, $ content = null) $ html = '
'; $ html. = '

Contenu de l'exemple de shortcode

'; $ html. = '
'; return apply_filters ('wptp_shortcode_html', $ html);

Le code HTML de notre shortcode peut maintenant être modifié comme ceci:

 fonction wptp_modify_html ($ html) return '
'. $ html. '
'; add_filter ('wptp_shortcode_html', 'wptp_modify_html');

Cela aura pour résultat que le code HTML original créé dans le shortcode sera enveloppé avec un autre div étiquette.

2. Messages d'interrogation

Effectuer des requêtes personnalisées dans les plugins est une pratique courante. Supposons un instant que vous ayez écrit un plugin qui enregistre un type de publication personnalisé appelé "livres" et que votre plug-in contienne une fonction permettant d'afficher les livres créés. Votre fonction d'interrogation des livres pourrait ressembler à ceci:

 function wptp_show_books () $ query_args = array ('post_type' => 'books', 'posts_per_page' => 5); $ books = new WP_Query ($ query_args); if ($ books-> have_posts ()): while ($ books-> have_posts ()): $ books-> the_post () // affiche les informations relatives à chaque livre ici endwhile; fin si; wp_reset_postdata (); 

Mais que se passe-t-il si un utilisateur souhaite modifier les types de livres qui ont été retournés, en sélectionnant peut-être uniquement des livres d'une catégorie spécifique? Vous pouvez leur faciliter la tâche en procédant comme suit:

 function wptp_show_books () $ query_args = array ('post_type' => 'books', 'posts_per_page' => 5, 'author' => 3); $ books = new WP_Query (apply_filters ('wptp_books_query', $ query_args)); if ($ books-> have_posts ()): while ($ books-> have_posts ()): $ books-> the_post () // affiche les informations relatives à chaque livre ici endwhile; fin si; wp_reset_postdata (); 

Le seul changement que j’ai fait est d’ajouter un filtre autour du $ query_args, ce qui signifie que d'autres développeurs (ou utilisateurs) peuvent modifier les arguments de la requête avant qu'ils ne soient réellement transmis à WP_Query. Par exemple, nous pourrions définir la requête pour afficher uniquement les livres de l'auteur 3, comme suit:

 fonction wptp_alter_books_query ($ args) $ args ['author'] = 3; return $ args;  add_filter ('wptp_books_query', 'wptp_alter_books_query');

3. Extension du balisage

Prenons maintenant l'exemple 2 et améliorons-le. Nous avons déjà ajouté un filtre permettant aux utilisateurs de modifier la requête. Ajoutons maintenant quelques points d'ancrage pour modifier le code HTML créé..

Commençons par modifier un peu notre code HTML original:

 function wptp_show_books () $ query_args = array ('post_type' => 'books', 'posts_per_page' => 5, 'author' => 3); $ books = new WP_Query (apply_filters ('wptp_books_query', $ query_args); if ($ books-> have_posts ()): echo '
'; while ($ books-> have_posts ()): $ books-> the_post () echo '
'; écho '

'. get_the_title (). '

'; écho '
'; en attendant; écho '
'; fin si; wp_reset_postdata ();

Nous aimerions maintenant permettre aux développeurs d’ajouter du balisage supplémentaire à différents moments, par exemple:

  • Avant que tout HTML soit sorti
  • Après la fin HTML
  • Avant le titre de chaque livre
  • Après le titre de chaque livre

Vous pouvez imaginer un scénario dans lequel un utilisateur voudrait ajouter une vignette avant ou après le titre du livre. Pour rendre cela possible, nous utilisons do_action () pour créer des emplacements pouvant être accrochés, comme ceci:

 function wptp_show_books () $ query_args = array ('post_type' => 'books', 'posts_per_page' => 5, 'author' => 3); $ books = new WP_Query (apply_filters ('wptp_books_query', $ query_args)); if ($ books-> have_posts ()): do_action ('wptp_books_before'); écho '
'; while ($ books-> have_posts ()): $ books-> the_post () echo '
'; do_action ('wptp_before_book_title', get_the_ID ()); écho '

'. get_the_title (). '

'; do_action ('wptp_after_book_title', get_the_ID ()); écho '
'; en attendant; écho '
'; do_action ('wptp_books_after'); fin si; wp_reset_postdata ();

Notez que les deux crochets intérieurs (entourant le titre) ont un deuxième paramètre de get_the_ID (). Cette variable, qui sera l'ID du livre, sera disponible en tant que paramètre pour toute fonction accrochée. Pour ajouter une vignette de livre, par exemple, nous pouvons faire ceci:

 fonction wptp_show_book_image ($ book_id) echo get_the_post_thumbnail ($ book_id, 'thumbnail');  add_action ('wptp_before_book_title', 'wptp_show_book_image');

Exemples du monde réel

Je voudrais maintenant vous montrer quelques exemples concrets d'extensions extensibles, y compris des exemples de certaines de leurs fonctions extensibles..

1. monologue

Soliloquy est un puissant plugin de slider image responsive pour WordPress qui permet de créer et de maintenir des sliders réactifs, efficaces, sécurisés et conviviaux pour le référencement.

Presque tout dans ce plugin est extensible. Voici juste un exemple:

 $ labels = apply_filters ('tgmsp_post_type_labels', array ('name' => __ ('Soliloquy', 'Soliloquy'), 'singular_name' => __ ('Soliloquy', 'Soliloquy'), 'add_new' => __ ( 'Ajouter un nouveau', 'Soliloque'), 'add_new_item' => __ ('Ajouter un nouveau curseur de monologue', 'Soliloque'), 'edit_item' => __ ('Modifier un curseur de soliloque', 'Monologue'), 'new_item' => __ ('New Soliloquy Slider', 'Soliloquy'), 'view_item' => __ ('View Soliloquy Slider', 'Soliloquy'), 'search_items' => __ ('Rechercher Soliloquy Sliders', 'Soliloquy') , 'not_found' => __ ('Aucun curseur de soliloque trouvé', 'Soliloque'), 'not_found_in_trash' => __ ('Aucun curseur de soliloque trouvé dans la corbeille'), 'parent_item_colon' => ",", 'nom_de_menu '=> __ (' monologue ',' monologue '))); $ args = apply_filters (' tgmsp_post_type_args ', array (' labels '=> $ labels,' public '=> true,' exclude_from_search '=> true,' show_ui '=> true,' show_in_admin_bar '=> false,' rewrite '=> false,' query_var '=> false,' menu_position '=> 100,' menu_icon '=> plugins_url (' css / images / menu-icon.png ', nom de répertoire (__FILE__)),' supports '=> array (' title ')));

C’est ainsi que Thomas Griffin (le développeur du plug-in) configure les arguments des étiquettes et des attributs de type de publication personnalisés. La présence de ses deux filtres, tgmsp_post_type_labels et tgmsp_post_type_args, il est très simple pour les autres développeurs de renommer le type de poste de curseur ou de modifier les supports pris en charge.

2. bbPress

De loin l’un de mes plugins préférés de tous les temps, bbPress est un plugin de forum complet pour WordPress. L'intégralité du plugin est un exemple parfait de la façon de rendre vos plugins extensibles, car il a littéralement des actions et des filtres partout. Il a un filtre particulier qui est appliqué lors de la récupération du contenu d'un forum:

 function bbp_get_forum_content ($ forum_id = 0) $ forum_id = bbp_get_forum_id ($ forum_id); // Vérifie si un mot de passe est requis si (post_password_required ($ forum_id)) renvoie get_the_password_form (); $ content = get_post_field ('post_content', $ forum_id); return apply_filters ('bbp_get_forum_content', $ content, $ forum_id); 

Avant que le contenu du forum ne soit renvoyé, il est transmis à travers un filtre appelé bbp_get_forum_content cela permet à un développeur de modifier le contenu avant qu'il ne soit affiché.

3. Téléchargements numériques faciles

Easy Digital Downloads, ou EDD, est l’un de mes plugins qui a été conçu pour rendre extrêmement facile la vente de produits numériques via WordPress. Comme avec la plupart des plug-ins de commerce électronique, EDD a mis en place un processus de paiement que l'acheteur effectue afin de pouvoir entrer ses informations personnelles et ses informations de paiement. Une fois toutes ces informations collectées, toutes les informations sont transmises à une passerelle de paiement (un système de traitement du paiement), mais avant que cette information ne soit transmise à la passerelle, un filtre est appliqué qui permet de manipuler les données avant leur utilisation par le paiement. système:

 $ purchase_data = apply_filters ('edd_purchase_data_before_gateway', $ purchase_data, $ valid_data);

La présence de ce filtre permet d’ajuster les montants des achats (éventuellement pour des remises spéciales), d’ajouter des taxes, d’ajouter ou de retirer des produits de l’achat, et bien plus encore..


Conclusion

Les plugins extensibles bénéficient à tout le monde: le développeur d'origine, les autres développeurs et les utilisateurs eux-mêmes..

Il y a tellement de raisons pour lesquelles vous devriez écrire vos plugins avec du code extensible en tête, alors pourquoi ne pas?

Les outils présentés ici constituent tout ce dont vous avez besoin pour commencer. Avoir des questions? Demander loin!