// BLOG
Kirby CMS - Les hooks
Déclencher l'execution d'une portion de code lorsqu'un évènement précis se produit dans votre site web est un mode de fonctionnement courrant dans les CMS. Ces évènements sont appelés "Hooks" et il en existe de nombreux dans Kirby CMS.
Qu'est ce que les hooks ?
Un hook est un point d'ancrage dans Kirby sur lequel nous pouvons greffer l'execution d'une portion de code. Ce point d'ancrage correspond à un évènement précis qui se produit soit suite à une action de l'utilisateur (dans le front ou le back aka Panel) soit suite à une action codée dans nos scripts.
Exemple de hooks dans Kirby :
- Création d'une page
- Suppression d'une page
- Changement de statut d'un utilisateur
- Modifier le nom d'un fichier ...
Il existe plus d'une trentaine de hooks dont la plupart sont déclinés en deux versions hook:before
et hook:after
Par exemple, on peut déclencher l'execution d'un code avant et/ou après la création d'une page.
Ces hooks sont très utiles pour automatiser certaines actions. Dans un CMS "Flatfile" dénué de base de données relationelles, ces hooks peuvent servirent par exemple à simuler l'aspect relationnel en déclenchant des suppressions entre des éléments de l'application qui sont étroitement liés.
Comment utiliser les hooks ?
Pour indiquer à Kirby que l'on souhaite executer une portion de code sur un évènement précis (un hook), il faut enregistrer ce hook soit dans le fichier de configuration /site/config/config.php
soit dans une section de votre plugin. Je n'aborderais pas dans cet épisode tout ce qui touche aux plugins car ça mériterait plusieurs articles mais si cela vous intéresse, je vous renvoie vers la documentation officielle.
Voici à quoi ressemble l'enregistrement de hooks dans le fichier de configuration de Kirby :
<?php
// /site/config/config.php
return [
'hooks' => [
'page.create:after' => function ($page) {
// code que je souhaite executer sur ce hook
},
'page.delete:before' => function ($page, $force) {
// code que je souhaite executer sur ce hook
}
]
];
Dans le tableau renvoyé par le fichier de configuration, il faut indiquer un indice litéral "hooks" dont la valeur est un tableau contenant la liste des hooks sur lesquels nous souhaitons intervenir. Le nom des hooks est assez explicite et se décline sur le pattern type.action:state
Pensez à respecter l'orthographe imposé par Kirby. La liste des paramètres qui seront accessibles dans notre code depuis un hook sont indiqués dans la documentation, l'ordre d'appel n'est pas stricte mais vous devez garder le nom qui leur est donné dans la documentation.
Enregistrement d'un hook dans le fichier de configuration :
Les wilcards hook
Si vous souhaitez appliquer une portion de code sur toutes les actions (suppression, création, modification ...) du même type de hook vous pouvez utiliser un wilcard hook.
Par exemple voici comment enregistrer un wilcard hook pour appliquer mon code sur les pages lors de tous les types de modification :
<?php
// /site/config/config.php
return [
'hooks' => [
'page.*:after' => function ($page) {
// code que je souhaite executer sur ce wilcard shook
},
]
];
Ce wilcard peut être utilisé sur le type
, l'action
ou l'état
du hook.
Par exemple, toutes ces combinaisons sont possibles:type.*:state
,
type.action:*
,
type.*.*:
,
*.action:state
,
*.action:*
,
*:state
,
*
Utilisation de l'objet $event
Un objet $event
peut être passé en paramètre de votre fonction anonyme pour ensuite accéder à des informations utiles comme par exemple le type
, l'action
, le state
... de votre hook. Voici l'ensemble des informations auxquelles vous pourez accéder :
<?php
// /site/config/config.php
return [
'hooks' => [
'page.create:before' => function ($event) {
$name = $event->name(); // 'page.create:before'
$type = $event->type(); // 'page'
$action = $event->action(); // 'create'
$state = $event->state(); // 'before'
$page = $event->page(); // $page
$input = $event->input(); // $input
}
]
];
Ces informations peuvent être utiles si vous souhaitez par exemple que votre hook réagissent uniquement à certaines actions.
Partons d'un exemple concret pour que cela soit plus claire. Supposons que je souhaite que mon code s'éxecute uniquement lorsqu'une page est soit créée soit supprimée. Voici comment je peux utiliser les informations fournies par l'objet $event
pour y arriver :
<?php
// /site/config/config.php
return [
'hooks' => [
'page.*:before' => function ($event, $page) {
// Vérifier si l'action doit être prise en compte
if ( in_array( $event->action(), ['create', 'delete']) !== true ) {
// Non, je retourne le résultat tout de suite et rien ne se passe !
return;
}
// Oui, j'execute mon code
...
return $result;
}
]
];
Accéder aux objets $kirby
, $site
et $user
Pour accéder aux objets Kirby dans le code appelé dans un hook, vous devez utiliser le mot clé this
de la manière suivante :
$kirby = $this;
$site = $this->site();
$user = $this->user();
Ce qui donne dans un hook :
<?php
// /site/config/config.php
return [
'hooks' => [
'page.create:after' => function ($page) {
// code que je souhaite executer sur ce hook
$site = $this->site();
$projects = $site->children()->filterBy('template','project');
...
}
]
];
Gestion des erreurs
Vous pouvez renvoyer des erreurs à l'utilisateur sous forme d'une modale. Si l'erreur est affichée, l'action ciblée dans le hook ne sera pas executée. On peut par exemple se servir de ce mécanisme pour valider des champs de formulaire du panel.
Voici comment afficher une modale d'erreur pour valider un champ requis :
<?php
// /site/config/config.php
return [
'hooks' => [
'page.create:after' => function ($page) {
// Si le champ creationDate est vide, j'affiche un message ...
if ( empty( $page->creationDate()->value() ) ) :
throw new Exception('La date de création est un champ requis.');
endif;
}
]
];