Les filtres et les actions sous WordPress #1 : les actions WordPress

code-php-boucle-wordpress-grand

Ce premier tutoriel à usage principalement des développeurs de plugins et intégrateur sous WordPress, a pour but de vous sensibiliser et de vous aider à la compréhension de l’API des actions WordPress.

Les filtres et les actions WordPress en quelques mots

Côté développeur, les filtres et les actions WordPress suffiraient à eux seuls à justifier, au regard de la concurrence, le choix de ce CMS comme outil de développement. En effet, cette fonctionnalité native de l’API de WordPress permet d’influer sur la quasi totalité du cœur du système sans pour autant modifier une seule ligne de code des fichiers sources. Une spécificité qui garantit entre autre la portabilité et la pérennisation de vos développements en cas de mise à jour du système; à l’exception bien sûr des fonctions du cœur  que vous auriez pu utiliser et qui auraient été rendues obsolètes (deprecated) lors de la mise à jour.

Facile à maîtriser du moment que l’on en ai saisi la philosophie et son fonctionnement, l’API des filtres et des actions WordPress décrites dans nos tutoriels vous permettra de coder mieux, plus simplement et en adéquation avec l’esprit du SGC le plus utilisé sur internet. Sachez qu’il n’est pas nécessaire d’être un foudre de guerre en développement pour comprendre ce tutoriel, quelques bonnes bases en PHP suffiront amplement. Que vous soyez développeur de plugins débutant, intégrateur ou graphiste, il vous permettra de mieux comprendre le fonctionnement de cette notion pour le moins incontournable.

Procédure de test de nos tutoriels

L’environnement de test de nos tutoriels est idéalement un WordPress fraichement installé (version 3.4.2 au moment de l’élaboration du tutoriel) avec pour thème actif, le thème natif Twenty Eleven (celui utilisé pour nos captures d’écran). Idéalement, aucune extension ne devrait être active pour éviter toute interaction.

Nous partirons du principe que tout le code de ce tutoriel sera, sauf exception notifiée, à inscrire dans le fichier functions.php du thème actif par défaut (Twenty Eleven). Cette méthodologie n’est pas anodine, puisqu’elle correspond, à quelques détails près, à la bonne pratique du développement sous WordPress.

Les actions WordPress par analogie

La philosophie des actions WordPress pourrait être comparée aux niveaux d’exécution de Linux, explications :

L’amorçage (boot) de Linux se déroule par le lancement de 7 niveaux d’exécutions consécutifs; de init 0 à init 6 (ces chiffres peuvent varier selon les distributions Linux). Chaque niveau correspond au lancement d’une série de services qui lui sont rattachés. Par exemple sous Debian (distribution Linux) l’environnement graphique est lancé durant l’init 2. Notons que ces services sont également hiérarchisés au sein de leur niveau d’affiliation, c’est à dire qu’il sont lancés dans un ordre bien déterminé pour s’assurer de l’implémentation des diverses dépendances.

Le fonctionnement des actions WordPress est très semblable à ce processus de démarrage de Linux. Ainsi à chaque ouverture d’une page du site internet, le cœur exécute une liste de tâches, on parlera d’actions, dans un ordre préétabli. Chacune de ces actions a à charge d’exécuter l’ ensemble des fonctions qui lui sont attribuées suivant l’ordre dans lequel ces dernières ont été déclarées (selon leur ordre d’apparition ou selon l’argument d’ordonnancement qui leur a été défini). Pas de panique, la suite va permettre de mettre en pratique et donc mieux intégrer les concepts de l’API WordPress.

Pour qualifier les niveaux d’exécutions dans WordPress, on emploi le terme de hook qui en traduction littérale signifie  crochet ou hameçon. Un terme particulièrement approprié puisque le fonctionnement de l’api des actions WordPress permet d’hameçonner des fonctions sur un hook selon un ordre hiérarchique défini.

Exécutez votre première action

Comme indiquez dans la procédure de test de nos tutoriels, rendez vous  dans un premier temps dans le fichier functions.php de votre thème actif.

Vue de la fonction functions.php dans un IDE (Aptana)

Arborescence du thème et functions.php dans un IDE (Aptana par ex.)

Puis saisissez le code suivant :

// Dire bonjour
function hello_milk(){
echo 'Hello Milk!';
}
add_action( 'init', 'hello_milk');

Après avoir rafraîchi votre navigateur vous devriez voir afficher sur votre site de test le message suivant : ‘Hello Milk!’.

Première action WordPress : Hello Milk!

Première action WordPress : Hello Milk!

L’appel à la fonction add_action sert à déclarer le contexte d’exécution de la fonction hello_milk. Le premier argument définit l’intitulé de référence du hook , ici init (tiens donc!?). Le second argument, lui correspond au nom de la fonction à exécuter.

Le choix du hook init dans le cas présenté est assez énigmatique, il aurait pu s’agir de tout autre : wp_loaded ou after_setup_theme ; la liste est conséquente. Vous trouverez d’ailleurs la liste des principaux hook lancés à chaque ouverture d’une page de site sous WordPress à cette adresse : Liste des actions WordPress. Cette liste est triée par ordre de déclenchement. Notez également qu’il existe parmi ces actions, des actions exécutées dans toutes les interfaces (interface d’administration ou back-office et interface de navigation utilisateur ou front-office); et d’autres exclusivement dans l’interface d’administration.

Définir l’ordre de déclenchement des fonctions dans une action

Plusieurs méthodes permettent d’influer sur l’ordre d’exécution des fonctions dans une action.

La première consiste à exécuter ces fonctions au travers de deux hook différents. L’ordre d’exécution des fonctions suivra respectivement l’ordre de déclenchement des ces actions que vous pourrez trouver dans la liste des actions WordPress précitée.

// Dire bonjour
function hello_milk(){
echo 'Hello Milk!';
}
add_action( 'init', 'hello_milk');

// Dire au revoir
function bye_milk(){
echo 'Bye Milk!';
}
add_action( 'wp_loaded', 'bye_milk');

L’action init étant exécuée avant l’action wp_loaded, le message « Hello Milk! » s’affiche donc avant le « Bye Milk! » ; à vrai dire c’était un peu l’effet escompté.

Agir sur l'ordre d'exécution des actions grâce à deux hook différents

Agir sur l’ordre d’exécution des actions grâce à deux hook différents

La deuxième méthode va permettre d’ordonner l’exécution de deux fonctions par le biais du même hook et donc de la même action, ce grâce à un argument supplémentaire.

// Dire ensuite au revoir
function bye_milk(){
echo 'Ensuite, Bye Milk!';
}
add_action( 'init', 'bye_milk', 2);

// Dire d'abord bonjour
function hello_milk(){
echo 'D’abord, Hello Milk!';
}
add_action( 'init', 'hello_milk', 1);

Volontairement, dans notre exemple, la fonction bye_milk est déclarée dans le code avant la fonction hello_milk. En effet, alternativement il est possible d’influer plus « simplement » sur l’ordre d’exécution des fonctions en les déclarant les unes après les autres. C’est alors le contexte d’exécution, à savoir PHP, qui prend le relais et assure cette tâche de hiérarchisation puisqu’il lit et exécute le code suivant l’ordre dans lequel il est inscrit dans les fichiers sources. Mais cette méthode présente finalement peu d’intérêt dans un contexte de production ; puisque les fonctions affiliées à un hook seront rarement inscrites dans le même fichier et il deviendrait vite présomptueux d’ espérer prévoir ou du moins d’organiser son code tout en s’assurant du bon ordre de déclaration des fonctions que l’on souhaite exécuter.

L’ajout d’un argument d’ordonnancement sous forme d’un entier permet donc de facilement influer sur l’ordre d’exécution des fonctions indépendamment de celui dans lequel elles sont inscrites dans les fichiers sources.

Agir sur l'ordre d'exécution des actions grâce à un argument

Agir sur l’ordre d’exécution des actions grâce à un argument

Dans l’exemple précédent on utilise à nouveau le hook init pour nos deux fonctions. En ajoutant pour troisième argument dans add_action, un entier ; on définit alors un ordre de priorité d’exécution de nos fonctions au moment du déclenchement de l’action.

Remarque :

La déclaration de l’argument d’ordonnancement permet aussi de dupliquer l’exécution d’une même fonction au travers du même hook. Mais très franchement ce cas d’école a très peu de chance de se présenter dans un contexte de production. Cette méthode n’aurait d’intérêt que si l’on a la possibilité avec la même fonction d’afficher deux contenus différents, mais ça c’est pour plus tard dans les lignes qui vont suivre.

// Dire Bonjour 2 fois avec la même fonction
function hello_milk(){
echo 'Hello Milk 2 fois!';
}
add_action( 'init', 'hello_milk', 1);
add_action( 'init', 'hello_milk', 2);

Créer des hook  et des actions personnalisées

Voyons à présent comment créer vos propres actions. Cette fois rendez vous d’abord dans le fichier index.php du thème et copiez le code suivant au début du fichier. Ce fichier est le template originel de la page d’accueil du thème Twenty Eleven utilisé pour nos tests. Copiez le code au début du fichier,  avant la déclaration de la fonction get_header().

do_action('hello_goodbye');

get_header(); ?>
 

Nous avons donc crée notre propre hook ayant pour intitulé de référence hello_goodbye. Reste à présent à lui adjoindre les fonctions que le déclenchement de l’action do_action(‘hello_goodbye’) aura à charge d’exécuter.

Dans le fichier functions.php copiez les lignes suivantes :

// Dire d'abord bonjour avec un action personnalisée
function hello_milk(){
echo 'D’abord, Hello Milk personnalisé!';
}
add_action('hello_goodbye', 'hello_milk', 1);

// Dire ensuite au revoir avec une action personnalisée
function bye_milk(){
echo 'Ensuite, Bye Milk personnalisé!';
}
add_action('hello_goodbye', 'bye_milk', 2);

Dans cet exemple, toutes les fonctions relatives au hook hello_goodbye seront déclenchées à l’appel du fichier index.php au moment de la déclaration do_action(‘hello_goodbye’). En l’absence d’argument d’ordonnancement, c’est l’ordre de déclaration des fonctions qui fait foi.

Créer et exécuter une action personnalisée

Créer et exécuter une action personnalisée

Passage d’arguments dans une action WordPress

Grâce aux déclencheurs d’action do_action outre l’argument d’ordonnancement il est possible de faire passer un ou plusieurs arguments personnalisés. Vous allez être alors en mesure de contextualiser vos fonctions affiliées selon cet argument.

Passage d’un argument unique

Testons dans un premier temps le passage d’un seul argument.

Notre environnement de test nécessite que vous soyez connecté via l’interface d’administration de WordPress puisque nous allons récupérer les données de l’utilisateur connecté. Ouvrez le fichier du thème index.php et modifiez le déclencheur d’action comme ceci :

wp_get_current_user();
do_action('hello_name', $current_user->display_name );

La fonction wp_get_current_user permet d’instancier la variable global $current_user, qui est un objet PHP contenant toutes les informations de profil de l’utilisateur courant.

Nous utiliserons cet argument dans la fonction pour personnaliser notre message :

// Dire bonjour à l'utilisateur courant
function hello_milk($name){
echo 'Hello '.$name.'!';
}
add_action('hello_name', 'hello_milk');

L’argument $current_user->display_name transit de la déclaration du déclenchement de l’action vers la fonction a exécuter ce qui permet sa récupération et donc son utilisation.

Créer et exécuter une action personnalisée avec un argument personnalisé

Créer et exécuter une action personnalisée avec un argument personnalisé

Passage de plusieurs arguments personnalisés

Il est tout à fait possible de faire passer plus d’un argument dans la déclaration de l’exécution de l’action :

wp_get_current_user();
do_action('hello_name_email', $current_user->display_name, $current_user->user_email );

En revanche il sera dans ce cas obligatoire de préciser à la fonction affiliée le nombre d’arguments qu’elle doit récupérer

// Dire bonjour à l'utilisateur courant et afficher son email
function hello_milk($name, $email){
echo 'Hello '.$name.'! Votre email est : '.$email;
}
add_action('hello_name_email', 'hello_milk', false, 2);

Si l’on veut récupérer tous les arguments du déclencheur do_action dans notre fonction hello_name_email, il faudra obligatoirement déclarer le nombre d’arguments qui transite lors de la déclaration add_action. C’est pourquoi la déclaration d’actions add_action possède un quatrième argument qui permet de définir le nombre d’arguments personnalisés qui peuvent transiter au travers de la fonction do_action. Sachant que la valeur par défaut autorise un seul argument personnalisé. Ce qui explique que nous n’ayons pas eu besoin de le préciser dans l’exemple précédent.

Vous aurez remarqué que le troisième argument (ordonnacement) a été fixé à false, une manière d’indiquer au système d’utiliser la valeur par défaut pour l’ordre d’exécution de la fonction à savoir 10. Vous trouverez toutes les indications (en anglais) sur la page du codex WordPress relative à la fonction add_action.

Passage de plusieurs arguments personnalisé dans une action

Passage de plusieurs arguments personnalisés dans une action

Passer les arguments dans un tableau

Il existe une autre fonction native dans l’api des actions WordPress qui peut servir de déclencheur. Il s’agit de la fonction do_action_ref_array. L’intérêt de cette fonction est qu’elle passe les arguments personnalisés par le biais d’un tableau indexé.

Même si elle est encore utilisée dans le code source de WordPress son intérêt est un peu tombé en désuétude avec le passage de PHP en 5.3. En effet, elle permettait de passer les arguments par référence (d’où son nom), ce qui est dorénavant le cas de do_action également.

En revanche do_action_ref_array impose l’existance d’un tableau d’arguments personnalisés alors que la déclaration do_action peut complétement se passer d’argument.

Dans cet exemple nous adapterons donc l’exemple précédent pour le déclencheur do_action_ref_array. Soit dans le fichier index.php :

wp_get_current_user();
do_action_ref_array('hello_name_email', array( $current_user ) );

Et dans le fichier functions.php :

// Dire bonjour à l'utilisateur courant et afficher son email
function hello_milk($user){
echo 'Hello '.$user->display_name.'! Votre email est : '.$user->user_email;
}
add_action('hello_name_email', 'hello_milk');

Le résultat sera le même que pour l’exemple précédent.

Fonctions supplémentaires de l’api des actions WordPress

Ce tutoriel sur l’utilisation de l’API des actions WordPress touche à sa fin. Vous devriez posséder l’essentiel des clefs pour attaquer vos premiers développements de thème ou de plugins.

Reste à faire un rapide tour d’horizon sur quelques fonctions supplémentaires de l’API et la manière de les utiliser :

did_action

Elle retourne le nombre de fois où une action a été déclenchée.

Exemple taper ceci dans le fichier index.php

do_action('tester_did_action'); do_action('tester_did_action');
var_dump( did_action('tester_did_action') );

Ce code devrait retourner la valeur 2;

has_action

Qui permet de vérifier si une action existe pour un hook donné et/ou une fonction affiliée.

Exemple dans le ficher functions.php

// Dire bonjour
function hello_milk(){
echo 'Hello Milk!';
}
add_action( 'tester_has_action', 'hello_milk', 8 );

Et dans le fichier index.php

var_dump( has_action('tester_has_action') );
var_dump( has_action('tester_has_action', 'hello_milk' ) );
var_dump( has_action('tester_has_action', 'fonction_inexistante' ) );
var_dump( has_action('hook_inexistant', 'hello_milk' ) );

La première ligne retourne true, il existe bien des fonctions liées à l’action tester_has_action

La deuxième ligne retourne 8, il existe bien une fonction hello_milk liée à l’action tester_has_action et elle a une priorité de 8

La troisième ligne retourne false, aucune fonction nommée fonction_inexistante n’est liée à l’action  tester_has_action

La quatrième retourne false, aucune fonction nommée hello_milk n’est liée à l’action  hook_inexistant

remove_action

Permet de retirer une fonction affiliée à une action selon son hook d’affiliation, le nom de la fonction, sa priorité, le nombre d’arguments qu’elle accepte.

remove_all_action

Permet de retirer toute les fonctions affiliées à une action, avec la possibilité de donner une suppression depuis un ordre de priorité.

Un tutoriel à paraître prochainement traitera de l’autre pendant de l’API des plugins WordPress, les filtres.

You can leave a response, or trackback from your own site.

Leave a Reply