Routing simple en PHP natif
Ce tutoriel vous permettra de mettre en place un routing simple en PHP natif. Ce routing respecte le MVC et est Orienté Objet.
Pourquoi faire un routing ?
Il est généralement considéré comme une mauvaise pratique de gérer les différentes pages d’un site au moyen des différents fichiers. En effet, de nombreuses pages ont souvent le même aspect, il vaut donc mieux savoir que telle url doit servir tel template et éviter de dupliquer inutilement du code.
PHP est un language qui permet de dynamiser des pages : profitons-en !
Tout commence par l’index
Le principe de base du routing en PHP est de rediriger toutes les requêtes vers le fichier index.php
qui se charge ensuite de traiter les informations et afficher les bons templates.
La version la plus simple de cette idée consiste à utiliser les paramètre $_GET
pour demander des informations à l’index.
Par exemple https://mon-site.com/index.php?route=blog&post_id=42
est une façon de demander à l’index d’afficher l’article de blog qui a l’id 42.
Par contre cette URL n’est pas très jolie, ni très ordonnée et n’est pas très SEO friendly. C’est pourquoi nous allons la réécrire.
Elle ressemblera plutôt à ceci : https://mon-site.com/blog/42
.
Réécrire des URLs
La réécriture d’URL c’est le travail du serveur. Lorsque votre serveur utilise Apache, cela se passe dans un fichier .htaccess
que vous placerez à la racine du site avec votre index.php
.
Le contenu du fichier .htaccess
:
N’oubliez pas de remplacer /the/path/to/your/
par le chemin vers votre index.php
.
Le fichier de configuration des routes
Pour rendre les routes plus simples à définir et modifier nous allons les réunir dans un fichier de configuration.
Nous créons donc un dossier config
à la racine de notre projet et nous ajoutons un fichier routes.txt
dans ce dossier.
Le contenu du fichier config/routes.txt
:
/ HomeController:index
/blog BlogController:index
/blog/* BlogController:show
Notre projet aura donc 3 routes possibles :
- La page d’accueil :
/
- La liste des articles du blog :
/blog
- Les détails d’un article du blog :
/blog/*
Ici le caractère *
signifie que l’on peut recevoir nímporte quoi après le /
.
Chaque route est donc représentée par une ligne avec le format suivant : path/parameter Controller:method
.
La paramètre du path est optionnel. La route /blog
ne prend pas de paramètre, mais la route /blog/42
prend un paramètre (ici 42
).
Les Controllers
En nous basant sur le fichier /config/routes.txt
nous pouvons déduire que nous aurons besoin de 2 controllers.
Nous allons les créer dans un nouveau dossier controllers
à la racine du projet.
Nos controllers seront assez simple, ils contiendront les méthodes indiquées pour les routes qui recevront les paramètres de la route si nécessaire et afficheront le template correspondant.
HomeController
Le contenu du fichier controllers/HomeController.php
:
BlogController
Le contenu du fichier controllers/BlogController.php
:
Les templates
Nos templates vont également être très simples. Ils vont uniquement servir à vérifier que notre routing fonctionne.
Nous allons les créer dans un nouveau dossier templates
à la racine du projet.
Nous n’utilisons pas de moteur de templates (comme Twig par exemple), nos fichiers de templates seront donc au format .phtml
.
home.phtml
Le contenu du fichier templates/home.phtml
:
blog_index.phtml
Le contenu du fichier templates/blog_index.phtml
:
blog_show.phtml
Le contenu du fichier templates/blog_show.phtml
:
Le Router
Notre Router va servir à analyser la requête et appeler le bon controller si la route demandée existe.
Nous allons le créer dans un nouveau dossier services
à la racine du projet.
Le contenu du fichier services/Router.php
:
Nous avons deux méthodes :
-
private function parseRequest(string $request)
qui sert à transformer lastring $request
en unarray
mieux organisé. -
public function route(array $routes, string $request)
qui appelleparseRequest
puis match la requête à son Controller et sa méthode.
Si la route n’existe pas, nous levons une Exception
.
Le paramètre array $routes
utilisé dans Router->route()
aura été défini au chargement de notre site dans l’autoload.
En PHP on peut appeler une classe ou une fonction depuis une string
qui contient le nom de la classe / fonction :
est donc l’équivalent par exemple de :
ou
L’autoload
Notre fichier autoload.php
que nous plaçons à la racine du projet va nous permettre de faire deux choses :
- faire des
require
des controllers et du routeur - charger la liste des routes depuis notre fichier de configuration
Le contenu du fichier autoload.php
:
Ouvrir et lire un fichier
Après avoir initialisé nos controllers et notre router, nous ouvrons le fichier config/routes.txt
et nous le parcourons ligne par ligne :
Trier les données du fichier
Nous voulons trier les données du fichier pour transformer chaque ligne en array
avec le format suivant :
Nous allons donc utiliser les fonctions de la librairie standard de PHP pour découper la string $line
et la stocker dans le tableau au format qui nous intéresse.
Puis nous allons placer chacune des routes que nous avons assemblé dans un array $routes
général qui contiendra toutes les routes possibles.
Nous utilisons str_replace
pour nettoyer notre string $line
et retirer les sauts à la ligne:
Puis nous séparons notre string $line
en deux string
de chaque côté du caractère espace :
Path et paramètre
Nous vérifions si notre route attend un paramètre en vérifiant le nombre de /
dans la string
:
Si oui nous précisons que la route attend un paramètre, et nous retirons le paramètre du path :
Si non, nous précisons que la route n’attend pas de paramètre :
Controller et méthode
Nous séparons le controller de la méthode en utilisant le caractère :
:
Et enfin nous ajoutons notre nouvelle $route
à la liste :
Fermer le fichier
Sans oublier de fermer le fichier une fois que nous avons terminé :
Assembler tous les éléments
Pour finir nous allons assembler tout ça depuis notre fichier index.php
:
Ici nous catchons en plus notre Exception
pour afficher une page 404 si la route n’existe pas.
Le contenu du fichier templates/404.phtml
:
Conclusion
Vous avez maintenant un routeur de base près à l’emploi. Vous pouvez aller plus loin en implémentant une hiérarchie dans vos templates et en ajoutant des managers que vous chargerez dans autoload.php
.
Vous retrouverez tout le code de ce tuto dans le repo Github.
Happy Coding !