(Tuto) PHP – Hook : Votre application modulaire
- Introduction au principe
- Mise en place des plugins et des fonctions de Hook
- Création des points de Hook de votre application
- Création des plugins qui seront appelés par les Hooks
- Conclusion
Dans les applications complexes (par exemple les Framework ou les CMS), il est de bonne pratique d’implémenter un système de plugins afin de séparer les fonctionnalités du coeur de votre système.
Les plugins permettent d’ajouter des fonctionnalités à votre application certes, mais qu’en est-il lorsqu’ils doivent « modifier » le comportement du noyau de votre logiciel ?
Cette problématique peut être résolue par un système de « Hook ». Un nom un peu étrange pour un système assez simple.
Introduction au principe
Un peu de théorie
Une application, en gros, c’est quoi ? Une succession de fonctions (ou méthodes) qui manipulent un bon nombre de variables (ou attributs). Afin de rendre modulaire un noyau, il faut donner le droit à notre plugin de modifier les variables de notre application. C’est grâce à notre système de Hook en PHP nous pourrons effectuer ce partage
!
Ok… Hook, Hook, c’est bien gentil, mais ça correspond à quoi concrètement ? Ça serait bien que tu nous expliques !
![]()
J’y viens
! Donc un système de Hook (littéralement système de « crochets ») est le fait de positionner des appels à des fonctions (de nos plugins) aux endroits stratégiques de notre script. Dans ces fonctions, on passe les paramètres par référence, ce qui a pour but de laisser la possibilité à notre fonction de modifier les valeurs des variables du script appelant.
Bah oui, mais on ne connait pas le nom de nos fonctions à l’avance… Comment on fait alors ?
![]()
Oui, effectivement, c’est bien vous suivez :D… pour cela on va stocker le nom des fonctions à appeler dans un tableau
.
Schématisation du fonctionnement
En gros, c’est comme si on fait quelque-chose comme ca :
// --------------------
// Dans le plugin
// --------------------
// On crée les fonctions qui devront être appelées dans notre application.
function plugin_ajouterTitre() {
...
}
function plugin_modifierContenu() {
...
}
// On stocke les noms des variables dans un tableau
$arrayFonctionsHook = array("plugin_ajouterTitre", "plugin_modifierContenu");
// --------------------
// Dans le noyau de l'application
// --------------------
// On inclue le plugin (et donc les fonctions)
include /* le plugin */;
// On appelle une à une les fonctions du plugin contenues dans le tableau
foreach($arrayFonctionsHook as $fonctionHook) {
$fonctionHook();
}
Ceci était un exemple très simple présentant brièvement le fonctionnement. Maintenant, on va attaquer les choses sérieuses
!
Mise en place des plugins et des fonctions de Hook
Inclure vos plugins dans votre application
Dans un premier temps, vous devez inclure vos plugins dans votre système. Pour cela, je vous conseille d’utiliser un répertoire spécifique qui sera lu avec la fonction glob() de PHP, comme ceci :
// On liste tous les fichiers qui se terminent par .plugin.php dans le dossier "plugins"
$arrayPlugins = glob(dirname(__FILE__) . '/plugins/*.plugin.php');
// S'il n'y a pas eu d'erreur de lecture du dossier et qu'il y a des fichiers dans le dossier
if(is_array($arrayPlugins)) {
// Pour chaque plugin trouvé dans le dossier
foreach($arrayPlugins as $plugin) {
// On va l'inclure
include $plugin;
}
}
Ce script va donc inclure tous les plugins qui sont situés dans le dossier « plugins » dans votre application
.
Créer une fonction d’enregistrement et une fonction d’appel de Hook
Afin de simplifier l’enregistrement des Hooks dans un array (ou tableau), on va créer deux fonctions : « addHook() » et « callHook() », que nous placerons dans la librairie de fonctions de votre application (vous devez sûrement avoir un fichier regroupant toutes vos fonctions non
? ).
Voici la fonction « addHook() » :
// Création de la fonction addHook() qui servira à l'enregistrement d'un nouveau Hook dans notre tableau de fonctions
// $hookName est le nom de notre hook
// $functionName est le nom de la fonction qui sera appelée lors de ce hook
function addHook($hookName, $functionName) {
// Enregistrement du nom de la fonction dans le tableau qui sera lu lors de l'appel du Hook $hookName
$GLOBALS['hooks'][$hookName][] = $functionName;
}
Pourquoi $hookName ? Il sert à quoi ?
![]()
Vous pouvez avoir plusieurs Hooks PHP dans votre application. Par exemple : un qui sera appelé après avoir généré un article, un autre avant d’enregistrer un utilisateur, ou encore avant d’afficher une image, etc… On va donc les différencier avec un nom unique pour chaque Hook
.
Et la fonction « callHook » :
// Création de la fonction callHook() qui permet d'appeler les fonctions enregistrées à un Hook donné.
// $hookName est le nom du Hook
// $hookArguments est un array qui contiendra tous les arguments à envoyer à notre fonction
function callHook($hookName, $hookArguments) {
// On regarde si des fonctions sont enregistrées à notre Hook
if(isset($GLOBALS['hooks'][$hookName])) {
// Si oui, on va appeler nos fonctions une à une avec call_user_func_array()
foreach($GLOBALS['hooks'][$hookName] as $functionName) {
call_user_func_array($functionName, $hookArguments);
}
return true;
}
else {
return false;
}
}
call_user_func_array() ? Ça appelle les fonctions ce truc ?
![]()
Oui
! C’est une fonction puissante qui permet d’appeler une fonction (dont le nom est pris en premier paramètre, dans notre cas « $functionName »), et de lui insérer des paramètres (contenus dans « $hookArguments »). De plus, cette fonction permet un passage des variables par « référence ».
Transférer des variables par référence à une fonction
En quoi ça consiste ? Quelle est la différence avec un passage de fonction « normal » ?
![]()
Attention, le principe est assez complexe donc assez difficile à suivre
. Lorsqu’on passe une variable à une fonction, une « copie » de celle-ci lui est transférée, ce qui fait qu’une modification de cette variable ne s’applique uniquement qu’à la fonction. On va donc dire que la portée de la variable est limitée à la fonction.
Un passage par référence partage la variable, c’est à dire que si la fonction modifie la variable, elle sera modifiée dans le script parent. La portée de la variable est donc globale dans le script.
Pour transférer une variable à une fonction par référence, il faut faire précéder le nom de la variable par un « & ». Comme ceci :
// Définition de la fonction qui modifiera les variables
function maFonction($variableCopiee, &$variableParReference) {
$variableCopiee = "modifiée";
$variableParReference = "modifiée";
}
// Définition des variables dans le script
$variableCopiee = "test1";
$variableParReference= "test2";
// Modification des variables avec l'appel de notre fonction
maFonction($variableCopiee, &$variableParReference);
// Affichage de nos variables
echo $variableCopiee;
echo $variableParReference;
// Affichera :
// "test1" et "modifiée"
Testez cet exemple et remarquez qu’une des deux variables est modifiée dans le script parent.
Création des points de Hook de votre application
Positionnez correctement vos points de Hook
Pour que votre plugin puisse modifier « utilement » votre application, vous devez soigneusement sélectionner l’emplacement de vos Hooks. Voici quelques exemples qui pourront vous inspirer :
- Avant et/ou après la récupération de vos articles en base de données,
- Lors de l’affichage d’un titre d’un article,
- Lors d’un enregistrement d’un utilisateur (ou d’un article) en base de données
- Lors de la modification d’un élément du site (catégorie, contenu, etc…)
- etc… En quelque sorte, tous les endroits où vous pensez qu’un plugin pourrait modifier votre application.
De toute manière, un système de Hook PHP doit répondre à un besoin, je vous conseille donc de rajouter vos Hooks lors du développement de vos plugins en pensant bien à une utilisation générique (pour d’autres plugins)
.
Appel des fonctions liées au Hooks
Afin d’appeler les fonctions qui sont enregistrées sur les Hooks nous allons utiliser la dernière fonction « callHook() » comme ceci :
// Code ...
callHook("EnregistrerUtilisateur", array(&$Utilisateur, $parrainId, $Site))
// Code ...
Dans notre exemple, les fonctions qui seront enregistrés pour le Hook « EnregistrerUtilisateur » devront avoir 3 paramètres (contenus dans l’array) : l’objet $Utilisateur (modifiable), le numéro du parrain $parrainId (non modifiable) et l’objet qui correspond au site auquel l’utilisateur s’est inscrit $Site.
Toutes les fonctions qui seront enregistrées au Hook « EnregistrerUtilisateur » seront donc appelées à cet endroit. Voyons maintenant comment créer une fonction qui sera liée à notre Hook d’exemple.
Création des plugins qui seront appelés par les Hooks
Cette étape est la plus simple, lorsque vous avez enregistré vos Hooks dans votre application, il vous suffit de créer des plugins pour les exploiter
. Voici un exemple de plugin qui va utiliser le Hook précédent (EnregistrerUtilisateur) :
Fichier : /plugin/modifierUtilisateur.plugin.php
// On définit une fonction qui modifie le login d'un utilisateur lors de la création
function plugin_modifierUtilisateur(&$Utilisateur, $parrainId, $Site) {
$Utilisateur->login = ucfirst(strtolower($Utilisateur->login));
}
// Ajout de la fonction au Hook qu'on a créé précédement (vous le reconnaissez ?)
addHook("EnregistrerUtilisateur", "plugin_modifierUtilisateur");
Et voilà, la fonction « plugin_modifierUtilisateur » sera appelée dans notre noyau
!
Conclusion
Pour conclure notre Tuto., on va récapituler les tâches réalisées pour mettre en place notre système de Hook en PHP :
- Création d’un bout de code qui inclura tous les fichiers *.plugin.php du dossier « plugin » de votre application
- Ajout de deux fonctions d’ajout et d’appel de Hook dans la librairie de fonctions de votre programme
- Mise en place de Hooks aux endroits stratégiques de votre script
- Création des plugins qui exploitent les Hooks de votre application.
Bien évidemment, ce système peut être largement amélioré. Par exemple, rajouter un entier lors de l’accrochage d’une fonction au Hook pour gérer les priorités (pour ceux qui doivent être exécutés avant ou après les autres) etc… Laissez libre à votre imagination pour d’améliorer ce système
.



Très intéressant ! Une bonne manière de simplifier le concept.
Juste, il manque un « p » à « lugin_modifierContenu » au moment de créer ton tableau $arrayFonctionsHook.
Erreur corrigée, merci pour le commentaire
Oui en effet, j’ai réalisé ce petit tutoriel pour présenter simplement les hooks par fonctions (car j’en avais besoin dans mon framework). J’avoue que sur internet, les renseignements sont assez maigres ou ils ne correspondaient pas à mes besoins.