// BLOG
Kirby CMS - Les routes
La notion de route dans les applications web correspond à l'adresse qu'il faufra indiquée pour arriver à bonne destination, en l'occurence une page web. Kirby étant par défaut en mode "Flat file", la notion de route à toute son importance. Vous n'avez généralement pas à vous souciez du routing des pages dans Kirby qui le gère de manière transparente. Cependant, dans certains cas particulier, vous pourriez être amené à définir vos propres routes.
Quand définir nos propres routes ?
Kirby gère automatiquement les routes des pages que vous crééez depuis le panel.
Emplacement physique | URL d'accès |
---|---|
/content/posts/first-post/post.txt | https://my-website.com/posts/first-post |
Imaginons maintenant que vous souhaitiez accéder à une page qui affiche des données qui ne proviennent pas d'un fichier texte contenu dans le dossier /content
(flux RSS, Sitemap, API, fichiers de données ...) ou que vous souhaitiez déclencher l'execution d'un programme en tappant une URL (génération d'un PDF ou d'un CSV ...). Dans ces cas, vous aurez besoin de définir vous même une route personnalisée dans le fichier de configuration de Kirby. Les cas sont nombreux où vous pourriez avoir besoin de créer vos propres routes, il est donc important de comprendre comment les implémenter dans votre projet Kirby.
Comment définir nos propres routes ?
Vous pouvez définir des routes personnalisées soit dans le fichier de configuration de Kirby qui se trouve dans /site/config/config.php
soit dans un plugin. Je n'aborderai pas la façon dont ont définie une route personnalisée dans un plugin, je vous renvoie vers la documentation officielle.
Le système de routing est déjà implémenté dans Kirby. Pour créer une route personnalisée, il suffit d'étendre ce système de routing à l'aide d'un tableau associatif dans lequel on passe des valeurs sur des mots clés prédéfinis qui sont routes
, pattern
et action
.
Voici à quoi cela va ressembler dans votre fichier de configuration :
// /site/config/config.php
return [
'routes' => [
[
'pattern' => 'mon/chemin/custom',
'action' => function () {
// le code à executer lorsque l'URL correspondante est appelée
}
],
]
];
Vous pouvez biensure ajouter autant de routes que vous le souhaitez dans le tableau 'routes' => []
Les patterns
La valeur passée à la clé pattern
peut être une chaîne de caractère indiquant une URL relative comme dans l'exemple précédent 'pattern' => 'mon/chemin/custom'
mais vous pouvez également utiliser des "placeholders" dynamiques. Ceux-ci permettent d'indiquer un format générique d'URL qui répondent à plusieurs expressions de route. Voyez ces placeholders dynamiques comme des Regex (expressions régulières). Kirby nous en propose quelque une prêt à l'emploi :
Placeholder | Description |
---|---|
(:all) | Prend en compte tous les caractères, y compris le slash / |
(:alpha) | Prend en compte tous les caractères alphabétiques entre a-z et A-Z |
(:alphanum) | Prend en compte tous les caractères alphanumériques entre a-z, A-Z et 0-9 |
(:any) | Prend en compte tous types de caractères jusqu'au prochain slash / |
(:num) | Prend en compte tous les nombres |
Vous pouvez également passer votre propre expression régulière [a-z]+
Voici un exemple d'utilisation des placeholders dynamiques dans la définition d'un pattern de route :
// /site/config/config.php
return [
'routes' => [
[
'pattern' => 'mon/chemin/(:any)/([a-z]+)',
'action' => function () {
// le code à executer lorsque l'URL correspondante est appelée
}
],
]
];
La fonction de callback passée sur l'option action
peut prendre en argument les placeholders dynamiques à condition de les passer dans l'ordre dans lequel ils sont utilisés :
// /site/config/config.php
return [
'routes' => [
[
'pattern' => 'mon/chemin/(:any)/(:num)/(:all)',
'action' => function($any, $num, $all) {
// le code à executer lorsque l'URL correspondante est appelée
}
],
]
];
Si vous souhaitez utiliser la même action pour plusieurs patterns différents, vous pouvez soit utiliser des expressions régulières, soit passer un tableau de patterns :
// /site/config/config.php
return [
'routes' => [
[
'pattern' => ['posts/(:any)', 'projects/(:any)', 'products/(:num)'],
'action' => function() {
// le code à executer lorsque l'URL correspondante est appelée
}
],
]
];
Les différents types de réponses
Selon les cas, la fonction de callback passée à la clé action
peut retourner différents types de résultats qui seront traitées en conséquence par Kirby.
Il peut sagir d'un objet Page
Pages
User
Users
File
Collection
... et tout type d'objet Kirby. Il peut aussi sagir d'une chaine de caractères avec ou sans balises HTML, d'une valeur null, vide ou booléen, un tableau de valeurs qui sera interprété comme un JSON, une Exception ...
// /site/config/config.php
return [
'routes' => [
[
'pattern' => 'fancy.json',
'action' => function () {
return [
'status' => 'ok',
'data' => ['foo' => 'bar']
];
}
],
[
'pattern' => 'index.html',
'action' => function () {
return '<html><body>Hello word !</body></html>';
}
],
[
'pattern' => 'mon/chemin',
'action' => function () {
throw new Exception('Alert !!!');
}
]
]
];
Les méthodes de requêtes
Par défaut les routes dans Kirby sont uniquement disponibles pour des requêtes de type GET mais vous pouvez préciser explicitement d'autres types de requêtes via la clé method
selon vos besoins :
// /site/config/config.php
return [
'routes' => [
[
'pattern' => 'mon/chemin',
'action' => function() {
// le code à executer lorsque l'URL correspondante est appelée
},
'method' => 'GET|POST|DELETE'
],
]
];
Voici les types de requêtes disponibles pour vos routes :
CONNECT
DELETE
GET
HEAD
OPTIONS
PATCH
POST
PUT
TRACE
La méthode next()
Il y a des scénarii où vous pourriez avoir besoin de déterminer si une URL appelée correspond à une certaine catégorie de pages et dans ce cas executer un script. Pour cela on va utiliser le pattern (:any)
pour intercepter toutes les URL et filtrer ces URLs selon une condition. Si la condition est vraie, on execute le script voulu, si pas, on veut que Kirby nous affiche la page. Cela est possible grâce à l'instruction $this->next()
// /site/config/config.php
return [
'routes' => [
[
'pattern' => '(:any)',
'action' => function($any) {
if ( page($any)->template() == 'post' ) :
// le code à executer
return $result;
endif;
$this->next();
},
],
]
];
Dans le code précédent :
'pattern' => '(:any)'
: On intercepte toutes les URLs.
if ( page($any)->template() == 'post' )
: On vérifie si la page est de type 'post', si oui on execute notre code et on renvoie un résultat.
$this->next()
: Si la condition n'est pas remplie (la page appelée n'est pas de type 'post'), kirby affiche la page en question sans executer quoi que ce soit.
Passer des données au controller ou au template
Depuis une route, vous pouvez passer un tableau de données dont chaque élément sera considéré comme une variable globale et donc accessible depuis le controller et/ou le template de la page que vous retournez, si c'est un objet Page que vous avez décidé de retourner dans fonction de callback.
Pour cela, il faut utiliser la méthode render()
// /site/config/config.php
return [
'routes' => [
[
'pattern' => '(:any)',
'action' => function($any) {
if ( page($any)->template() == 'post' ) :
$data = [
'slug' => $any,
];
return page('posts')->render($data);
endif;
$this->next();
},
],
]
];
Dans le code précédent, je renvoie la page posts
et lui associe un tableau dans lequel se trouve le slug de la page qui vient d'être appelée. La variable $slug
sera alors disponible dans le controller de la page posts
:
<?php
// /site/controllers/posts.php
return function ($page, $slug) {
// Code de mon controller ... qui a accès à la valeur de $lug
return [
'post_title' => page($slug)->title()
];
};
... mais aussi dans le template correspondant si besoin :
<?php
// /site/templates/posts.php
<h2><a href="<?= page($slug)->url() ?>">$post_title</a></h2>
Le hook "route"
Vous disposez avec Kirby d'un hook "route" avec les deux états route:before
et route:after
Vous pouvez donc executer un code personnalisé juste avant qu'une page (avec un pattern d'URL particulier ou pas) soit appelée ou juste après.
Exemple :
// /site/config/config.php
return [
'hooks' => [
'route:before' => function ($route, $path, $method) {
if ( $path === 'super/secret' && !kirby()->user() ) {
die();
}
}
]
];
Dans le code précédent :
'route:before' => function ($route, $path, $method) {
: On surveille lorsqu'une page est appelée et on execute un code juste avant que la page soit renvoyée par Kirby.
if ( $path === 'super/secret' && !kirby()->user() ) {
: On teste que la page appelée soit https://monsite.com/super/secret
et on teste si l'utilisateur est connecté.
Si c'est bien cette page et que l'utilisateur n'est pas connecté, on lui refuse l'accès. Un moyen simple de restreindre l'accès à certaines pages de votre front-end.
Route et page virtuelle
Les routes peuvent aussi retourner, ce que l'on appelle dans Kirby, des pages virtuelles c'est à dire des pages qui n'existent pas physiquement dans le système de fichier du dossier /content
mais qui sont alimentés par des données provenant de sources externes. Je ne vais pas en dire plus sur les pages virtuelles, celles-ci faisant l'objet d'un article à part entière.
Accedéder aux paramètres et "query string"
Les paramètres et les query string ne peuvent pas être indiqués au niveau du pattern de la route. Cependant ils peuvent être récupérés à l'aide des méthodes "helpers" param()
et get()
de Kirby.
// /site/config/config.php
<?php
return [
'routes' => [
[
'pattern' => 'products/(:any)',
'action' => function($uid) {
// parameter, e.g. `https://example.com/products/color:black`
if ($param = param('color')) {
// do something
}
// query string, e.g. `https://example.com/products?color=black`
if ($query = get('color')) {
// do something
}
// ...
}
],
]
];