Routes
Nous allons maintenant passer à la mise en place du routage. Après avoir redirigé toutes les requêtes vers index.php et supprimé les extensions .php des liens, nous pouvons contrôler précisément quelle URL correspond à quelle ressource. Le routage nous permettra de créer des URLs personnalisées, lisibles et indépendantes de la structure des fichiers, en associant chaque URL à un contrôleur et à une action définis dans un tableau de routes.
Méthode : app/routes.php
Exemples de routes :
utilisateurs→[utilisateur, index]utilisateur/afficher-3→[utilisateur, show]
<?php
$routes = [];
// $routes[] = [path, name, [controller, action]];// path : url de la ressource. {param} indique l'utilisation d'un paramètre// name : clé unique de la route// controller : dossier où se trouve réllement la ressource// action : nom du fichier de la ressource sans son extension$routes[] = ['/', 'home.index', ['home', 'index']];
$routes[] = ['/utilisateurs', 'utilisateur.index', ['utilisateur', 'index']];
$routes[] = ['/utilisateur/ajouter', 'utilisateur.create', ['utilisateur', 'create']];
$routes[] = ['/utilisateur/afficher-{id}', 'utilisateur.show', ['utilisateur', 'show']];
$routes[] = ['/utilisateur/modifier-{id}', 'utilisateur.update', ['utilisateur', 'update']];
$routes[] = ['/utilisateur/supprimer-{id}', 'utilisateur.delete', ['utilisateur', 'delete']];
path — le chemin de l’URL
Définition : C’est l’URL publique qui sera utilisée par les visiteurs pour accéder à la ressource.
Format : Chaîne commençant par
/, avec possibilité de paramètres dynamiques indiqués par{param}.Paramètres dynamiques :
Tout segment entouré de
{}devient une variable capturable.Exemple :
{id}→/utilisateur/afficher-3donneid = 3.
But : Permet d’avoir des URLs propres, lisibles et indépendantes des noms de fichiers réels.
name — identifiant unique de la route
Définition : C’est une clé unique qui identifie la route dans votre application.
Utilité :
Générer des URLs dans votre code sans les coder en dur.
Référencer une route de manière stable même si le
pathchange.
On peut penser à name comme à un alias pour la route.
[controller, action] — le contrôleur et l’action associée
controller
Définition : Le dossier dans
app/controllersoù se trouvent les fichiers PHP qui gèrent cette route.Exemple :
utilisateur→ les fichiers se trouvent dansapp/controllers/utilisateur/.
action
Définition : Le fichier PHP correspondant à la route, sans l’extension
.php.Exemple :
show→ le fichier complet estapp/controllers/utilisateur/show.php.
Rôle du couple controller/action
Le contrôleur contient la logique de traitement de la requête.
L’action correspond à la ressource exacte à exécuter pour cette route.
Ensemble, ils permettent à
index.php(le front controller) de savoir quel fichier inclure et exécuter pour répondre à l’URL demandée.
Méthode : app/helpers.php
Le fichier helpers sert à regrouper des fonctions destinées à simplifier l’écriture du code. Nous devons y ajouter les fonctions suivantes dans app/helpers.php.
Méthode : function url(): string
La fonction url sert à récupérer l’URL demandée
function url(): string
{ // Nettoyer le chemin du script (remplace \ par / pour Windows)$scriptDir = str_replace('\\', '/', dirname($_SERVER['SCRIPT_NAME']));
// Supprimer les paramètres GET$requestUri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// Supprimer le dossier du scriptif (strpos($requestUri, $scriptDir) === 0) {
$requestUri = substr($requestUri, strlen($scriptDir));
}
// Nettoyer les éventuels / en début et fin, ajouter un / au débutreturn '/' . ltrim($requestUri, '/');
}
Méthode : function getRoute(array $routes, string $url): ?array
La fonction getRoute sert à trouver quelle route correspond à l’URL demandée et à récupérer les informations nécessaires pour exécuter la bonne ressource.
En pratique :
Elle parcourt toutes les routes définies dans
$routes.Elle compare l’URL demandée avec le
pathde chaque route.Si l’URL correspond :
Elle retourne le contrôleur à utiliser (
controller).Elle retourne l’action à exécuter (
action).Elle extrait les paramètres dynamiques de l’URL (comme
{id}) pour que le contrôleur puisse les utiliser.
Si aucune route ne correspond, elle retourne
null
function getRoute(array $routes, string $url): ?array
{foreach ($routes as $route) {
$path = $route[0];
// Transformer le path en expression régulière pour détecter les paramètres$pattern = preg_replace('/\{(\w+)\}/', '(?P<$1>[^/]+)', $path);
$pattern = "#^$pattern$#";
if (preg_match($pattern, $url, $matches)) {
// Extraire uniquement les paramètres nommés$params = array_filter(
$matches,fn($key) => !is_int($key),
ARRAY_FILTER_USE_KEY);
return ['controller' => $route[2][0],
'action' => $route[2][1],
'params' => $params
];
}
}
// Aucun route trouvéereturn null;
}
Méthode : function route(string $name, array $params = []): string
La fonction route permet de générer automatiquement l’URL correspondant à une route définie, sans avoir à l’écrire manuellement.
Elle prend en entrée le nom de la route (
name) et éventuellement des paramètres dynamiques (par exempleid).Elle retourne l’URL complète prête à être utilisée dans un lien ou un formulaire.
Exemples dans vos liens href ou dans vos header :
< ?= route('home.index') ?>
< ?= route('utilisateur.show', ['id' => 3]) ?>
header('location:' . route('utilisateur.index'));
function route(string $name, array $params = []): string
{global $routes;
foreach ($routes as $route) {
if ($route[1] == $name) {
$url = $route[0];
foreach ($params as $key => $val) {
$url = str_replace('{' . $key . '}', $val, $url);
}
return dirname($_SERVER['SCRIPT_NAME']) . $url;
}
}
return '';
}
Méthode : function getParams($key, $default=null): string|int|null
La fonction getParams permet de retourner la valeur de la clé se trouvant dans la route.
function getParams($key, $default = null): string|int|null
{return $GLOBALS['route']['params'][$key] ?? $default;
}
Méthode : function view($name, $vars = []): void
La fonction view() permet d’inclure une vue (un fichier PHP de app/views) et de lui transmettre des variables. Elle simplifie donc l’affichage du contenu depuis un contrôleur.
Exemple dans vos contrôleurs :
return view('utilisateur.update', compact('page_title', 'page_styles', 'utilisateur'));
La fonction calcule et transmet désormais $page_base ; les contrôleurs n’ont donc plus besoin de le fournir.
function view($name, $vars = []): void
{extract($vars);
// Calcul du chemin relatif vers la racine du site$nbPath = max(0, count(explode('/', trim(url(), '/'))) - 1);
$page_base = str_repeat('../', $nbPath);
// On remplace les . par des / pour obtenir le chemin du fichier$url = str_replace(".", "/", $name);
// Inclusion du fichier de la vue s'il existeif (is_file("../app/views/$url.php")) {
require "../app/views/$url.php";
return;}
// Inclusion du fichier index.php dans le dossier de la vue s'il existeif (is_file("../app/views/$url/index.php")) {
require "../app/views/$url/index.php";
return;}
// Sinon, message d'erreurecho "La vue $name est introuvable.";
}
Méthode : function redirect(string $routeName, array $vars = []): void
La fonction redirect() permet de rediriger l’utilisateur vers une autre page du site en utilisant le nom d’une route. Elle simplifie le code en encapsulant l’appel à header() et exit.
Exemple dans vos contrôleurs :
return redirect('utilisateur.index');
function redirect(string $routeName, array $vars = []): void
{ // Génération de l'URL à partir du nom de la route$url = route($routeName, $vars);
// Redirection HTTPheader("Location: " . $url);
exit;}
Méthode : public/index.php
Il est nécessaire de mettre à jour le Front Controller pour qu’il exploite les fonctions définies dans le fichier helpers ainsi que le système de routes.
// ==============================// INCLUSION DES FONCTIONS// ==============================require '../app/models/model.php';
require '../app/helpers.php';
require '../app/routes.php';
// ==============================// RÉCUPÉRATION DE L’URL // ==============================$url = url();
// ==============================// RÉCUPÉRATION DE LA ROUTE // ==============================$route = getRoute($routes, $url);
// ==============================// RECUPERATION DU CONTRÔLEUR ET DE L’ACTION// ==============================if ($route) {
$controller = $route['controller'];
$action = $route['action'];
} else {$controller = 'error';
$action = 'index';
}
// ==============================// INCLUSION DE LA RESSOURCE// ==============================$file = "../app/controllers/$controller/$action.php";
if (!file_exists($file)) {
http_response_code(404);
$file = "../app/controllers/error/index.php";
}
require $file;
Méthode : controllers
Il est nécessaire de mettre à jour les Controllers afin qu’ils utilisent les fonctions définies dans le fichier helpers.
On supprime les références à $page_base.
Tous les
requirevers les vues sont remplacés par la fonctionview().
Les lignes
$id = (int)($_GET['id'] ?? 0);deviennent$id = (int)getParams('id');.
Enfin, toutes les fonctions
headeret leexitsont remplacées par la fonctionredirect().
Par exemple :
require '../app/views/utilisateur/show.php';
devient
return view('utilisateur.show', compact('page_title', 'page_styles', 'utilisateur'));La fonction view() ne connaît que ce qu’on lui transmet. En PHP, une fonction possède son propre scope (espace de variables).
Les variables définies dans le contrôleur ne sont donc pas automatiquement disponibles dans la vue. Il faut les passer explicitement en paramètre.
header('location:index');exit;
devient
return redirect('utilisateur.index');Méthode : views
Toutes les références aux liens du site dans les attributs href des vues doivent être mises à jour.
Ainsi que tous les require vers les vues sont remplacés par la fonction view().
Par exemple :
<li><a href=''>Accueil</a></li>
devient
<li><a href='= route('home.index') '>Accueil</a></li>
<a href="utilisateur/show?id== $utilisateur['id'] ">
devient
<a href="= route('utilisateur.show', ['id' => $utilisateur['id']]) ">
require '../app/views/head.php';
devient
view('head', compact('page_title', 'page_styles'));
view étant une fonction, il ne faut pas oublier de lui transmettre les variables utiles à la vue.
$photoDir = '../images/photos/';
devient
$photoDir = 'images/photos/';
Méthode :
Nous pouvons désormais vérifier le bon fonctionnement du site et constater que les URLs sont réécrites conformément à celles définies dans les routes.