Quand on commence à développer un site web avec PHP, il est courant de regrouper tout dans un seul fichier index.php
. Ce fichier devient alors le point d’entrée principal de votre application. Mais rapidement, cette organisation devient difficile à maintenir, surtout lorsqu’on veut structurer proprement son code avec le modèle MVC (Modèle-Vue-Contrôleur). D’où l’importance du routeur et de la segmentation des fichiers de Vues à l’aide d’un layout.
Pour éviter de vivre cela avec notre projet Créa-code, où l’architecture va progressivement s’enrichir au fil des jours, pour ce treizième jour , nous allons franchir une étape essentielle : la mise en place d’un routeur indépendant et d’un système de layout réutilisable. Ces deux éléments sont les piliers d’une application web bien structurée.
Dans ce tutoriel, nous allons vous expliquer pas à pas, ce que sont un routeur et un layout, pourquoi ils sont essentiels, et comment nous les avons intégrés de façon propre et sécurisée dans notre architecture MVC.
- Qu’est-ce qu’un routeur en PHP ?
- Qu’est-ce qu’un layout ?
- Le contexte Créa-code : une architecture MVC en PHP à faire évoluer
- Étape 1 : Extraire le routeur vers un fichier dédié
- Étape 2 : Sécuriser le routeur
- Étape 3 : Layout global avec header.php et footer.php
- Étape 4 : Sécuriser le layout (headers HTTP)
- Étape 5 : Ajouter des routes dynamiques avec paramètres
- Étape 6 : Mettre en place un système de middleware
- Étape 7 : Vers un moteur de template plus avancé
- Étape 8 : Récapitulatif de la nouvelle structure MVC de Créa-code
Qu’est-ce qu’un routeur en PHP ?
Un routeur, dans le contexte du développement web, est un mécanisme qui permet de relier une URL à une action spécifique de votre code. Autrement dit, c’est lui qui décode l’adresse que vous tapez dans votre navigateur (par exemple /user/show/12
) pour déterminer quel contrôleur et quelle méthode doivent être appelés, et avec quels paramètres.
Imaginez un standardiste qui reçoit les appels (vos URL) et qui transfère ces appels à la bonne personne (votre contrôleur). C’est exactement ce que fait un routeur.
Le rôle du routeur
Le routeur est un peu comme un GPS pour votre site web. Lorsqu’un visiteur tape une adresse dans son navigateur, c’est le routeur qui décode cette adresse pour savoir quelle page lui afficher. Par exemple, si quelqu’un visite https://code.crea-troyes.fr/profil/5
, le routeur va comprendre qu’il faut appeler la méthode profil
du contrôleur UserController
avec l’identifiant 5. Sans lui, toutes les pages devraient être codées à la main, ce qui serait très long et difficile à gérer.
Sur le site Créa-code, le routeur va donc permettre de rendre les URLs claires et logiques. Il gère aussi les paramètres dynamiques (comme les identifiants d’utilisateur,…). Grâce à lui, on peut ajouter de nouvelles pages sans dupliquer du code. Il sécurise aussi l’accès en redirigeant, par exemple, les utilisateurs non connectés vers la page de connexion si une page est protégée.

Exemple de l’interprétation d’une url par le routeur :
- URL :
/user/show/12
- Contrôleur appelé :
UserController
- Méthode :
show
- Paramètre :
12
(souvent l’identifiant d’un utilisateur)
Sans routeur, on aurait dû écrire des fichiers séparés pour chaque action (
showUser.php
,editUser.php
, etc.), ce qui deviendrait vite ingérable.
Qu’est-ce qu’un layout ?
Un layout est un gabarit commun à toutes vos pages. C’est ce qui contient les éléments récurrents de votre site, comme :
- le header (menu de navigation, logo, etc.),
- le footer (informations, liens utiles…),
- et un contenu central qui change selon la page.
Grâce à un layout, vous ne répétez plus le code HTML de la structure de votre page dans chaque vue. Vous factorisez tout ce qui est commun.

Le rôle du layout
Un layout, c’est une structure de base qui sert à afficher toutes les pages de façon cohérente. Il contient des éléments fixes comme l’en-tête (le header) et le pied de page (le footer), qui ne changent pas d’une page à l’autre. Au milieu, on insère le contenu propre à chaque page. C’est comme un cadre photo où l’on glisse une nouvelle image à chaque fois.
Pour Créa-code, cela veut dire que toutes les pages partagent le même menu de navigation, le même style global, et la même structure HTML. Cela rend le site plus professionnel, plus facile à maintenir, et plus agréable pour l’utilisateur. Si un jour vous voulez modifier le menu ou ajouter un bandeau d’information, il suffit de le faire une seule fois dans le layout, et toutes les pages seront mis à jour.
Le contexte Créa-code : une architecture MVC en PHP à faire évoluer
Au départ (jour 12 : Création de l’architecture MVC en PHP d’un site web), notre fichier index.php
ressemblait à ceci (version simplifiée de ce que l’on avait codé) :
$url = $_GET['url'] ?? '';
$segments = explode('/', trim($url, '/'));
$controller = ucfirst($segments[0]) . 'Controller';
$method = $segments[1] ?? 'index';
Il analysait l’URL, détectait le contrôleur et la méthode, et appelait la bonne fonction avec les bons paramètres. Ce système simple fonctionne, mais il devrait vite nous montrer ses limites :
- difficile d’ajouter de la sécurité (liste blanche, validation),
- impossible de centraliser les routes (comme dans CodeIgniter ou Laravel),
- aucune prise en charge de routes dynamiques du type
/profil/12
, - aucun système de middlewares pour protéger certaines pages.
Il nous faut donc refactoriser notre architecture en déportant cette logique dans un fichier Router.php
dédié, dans le dossier app/Route/
et définir les routes dans le fichier app/Route/Routes.php
.
Étape 1 : Extraire le routeur vers un fichier dédié
Voici notre nouveau fichier public/index.php
bien plus minimaliste mais non moins efficace :
<?php
session_start();
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../autoload.php';
require_once __DIR__ . '/../app/Route/Routes.php';
Ce changement peut paraître minime, mais il est crucial. Toute la logique de routage est désormais contenue dans la classe Router
qui sera appelé par le fichier Routes.php
(nous allons coder ces fichiers un peu plus loin). Cela nous permettra de :
- concentrer la logique de routage dans un seul fichier,
- modifier et améliorer cette logique sans toucher au cœur de l’application,
- tester le routeur indépendamment du reste.
Étape 2 : Sécuriser le routeur
Un bon routeur doit être robuste face à des entrées malicieuses ou inattendues. Dans notre première version, nous avions ajouté des filtres :
- Vérification que le contrôleur correspondait à un nom valide (
NomController
), - Vérification que la méthode etait une chaîne autorisée (lettres, chiffres, underscore),
- Liste blanche des contrôleurs et des méthodes.
Cela empêchait un utilisateur malintentionné de faire appel à des classes sensibles ou d’exécuter du code imprévu.
Nous avions aussi prévu de valider les paramètres transmis via l’URL dans les méthodes elles-mêmes, pour garder le contrôle jusqu’au bout. Nous allons également faire évoluer ce principe.
Étape 3 : Layout global avec header.php
et footer.php
Au niveau de l’affichage, nous allons créé un fichier layout.php
qui rassemblera :
header.php
contenant le début du HTML, les balises meta, les headers HTTP de sécurité, le menu,…footer.php
contenant le pied de page, les scripts JS, la fermeture des balises,…-
<?= $content ?>
au centre, pour afficher dynamiquement la vue demandée.
Dans chaque contrôleur, nous appellerons désormais une méthode dédiée pour charger les vues avec le layout :
View::render('home/index', compact('title'));
Cette méthode utilisera un petit moteur de rendu PHP qui fait un ob_start()
pour capturer le contenu de la vue et l’injecter dans le layout.
Consultez nos tutoriels pour en savoir plus sur Le layout en PHP et La mise en mémoire tampon.
Étape 4 : Sécuriser le layout (headers HTTP)
Notre fichier header.php
enverra désormais des headers de sécurité importants :
header("X-Content-Type-Options: nosniff");
header("X-Frame-Options: SAMEORIGIN");
header("X-XSS-Protection: 1; mode=block");
Ces lignes renforcent la protection contre certaines attaques comme les injections JavaScript ou les chargements externes non souhaités. Cela ne remplace pas un pare-feu applicatif, mais c’est une excellente première couche de sécurité.
Consultez notre tutoriel pour en savoir plus sur Les headers HTTP en PHP.
Étape 5 : Ajouter des routes dynamiques avec paramètres
Une limitation de nombreux routeurs basiques en PHP est l’incapacité de gérer les routes dynamiques, comme par exemple :
/profil/42
/article/mon-article-de-blog
/quiz/html/introduction
Avec notre ancienne architecture, ces paramètres étaient juste récupérés comme des segments d’URL. Mais rien n’indiquait quelle route faisait quoi, ni s’il s’agissait d’un identifiant, d’un slug ou d’un mot-clé.
Pour y remédier, nous ajoutons un système d’enregistrement de routes dans notre classe Router
. Chaque route peut maintenant être enregistrée ainsi dans le fichier Routes.php
:
$router->get('/profil/{id}', 'UserController@profil');$router->get('/article/{slug}', 'BlogController@show');
Le routeur convertit automatiquement {id}
ou {slug}
en expressions régulières pour capturer les paramètres dans l’URL.
Quand vous visitez /profil/42
, le routeur comprend que 42
est un paramètre nommé id
, et l’envoie automatiquement à la méthode profil()
du UserController
.
Cela permettra d’écrire un code plus clair dans nos contrôleurs, comme par exemple futurement :
public function profil($id) {
// on vérifie si l’ID est valide
// on récupère l’utilisateur depuis la base
// on affiche la vue correspondante
}
C’est la base d’un véritable système de routage moderne.
Étape 6 : Mettre en place un système de middleware
Un middleware est un filtre que l’on applique avant (ou après) l’accès à une route. Cela permettra, par exemple, de :
- vérifier que l’utilisateur est connecté,
- s’assurer que l’utilisateur est administrateur,
- appliquer des règles de rate limiting.
Dans notre architecture MVC, nous allons donc ajouter la possibilité d’attacher un middleware à une route :
$router->registerMiddleware('auth', function () {
if (!isset($_SESSION['user'])) {
header('Location: /public/login');
return false;
}
return true;
});
$router->get('profil', 'UserController@profil')->middleware('auth');
Le routeur vérifie automatiquement si le middleware auth
est respecté, et sinon redirige vers une page de connexion. Cela permet de protéger certaines routes sans devoir écrire du code conditionnel dans chaque contrôleur.

Des formations informatique pour tous !
Débutant ou curieux ? Apprenez le développement web, le référencement, le webmarketing, la bureautique, à maîtriser vos appareils Apple et bien plus encore…
Formateur indépendant, professionnel du web depuis 2006, je vous accompagne pas à pas et en cours particulier, que vous soyez débutant ou que vous souhaitiez progresser. En visio, à votre rythme, et toujours avec pédagogie.
Découvrez mes formations Qui suis-je ?Il devient aussi possible de créer plusieurs middlewares (auth
, guest
, admin
, verified
, etc.) que l’on applique au niveau des routes ou même des groupes de routes.
Étape 7 : Vers un moteur de template plus avancé
Notre moteur de rendu de vue est pour l’instant très simple. Il repose sur ob_start()
pour capturer le contenu d’une vue et l’injecter dans le layout global.
Mais il est possible d’aller plus loin en s’inspirant de ce que proposent certains framework.
La class app/Core/View.php
<?php
namespace App\Core;
class View
{
public static function render(string $viewPath, array $data = []): void
{
extract($data); // Ex : $title, $content
ob_start();
require __DIR__ . '/../Views/' . $viewPath . '.php';
$content = ob_get_clean();
require __DIR__ . '/../Views/layout.php';
}
}
Et app/Views/layout.php :
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title><?= e($title ?? 'Créa-code'); ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/css/styles.css">
</head>
<body>
<?php require_once __DIR__ . '/partials/header.php'; ?>
<main class="container">
<?= $content ?? ''; ?>
</main>
<?php require_once __DIR__ . '/partials/footer.php'; ?>
</body>
</html>
Pourquoi ce système est utile ?
Il vous permet de :
- segmenter vos vues en blocs (
title
,content
,scripts
, etc.), - remplacer facilement une section depuis une vue enfant,
- réutiliser vos composants (comme
alert.php
,form.php
, etc.), - préparer le terrain pour une future modularisation (avec des composants comme dans Laravel ou React).
Nous n’avons pas encore intégré toutes ces fonctionnalités, mais la structure actuelle est prête à les accueillir. L’idée n’est pas de réinventer le principe d’un framework, mais de reproduire ses principes avec des fonctions simples en PHP natif.
Étape 8 : Récapitulatif de la nouvelle structure MVC de Créa-code
Voici un résumé complet de l’architecture du projet à ce stade :
code.crea-troyes.fr/
│
├── public/ (dossier web accessible)
│ └── assets/
│ ├── style.css
│ └── index.php (point d'entrée unique)
│ └── .htaccess
│
├── app/
│ ├── Controllers/
│ │ ├── HomeController.php
│ │
│ ├── Models/
│ │ └── Model.php
│ │
│ ├── Views/
│ │ ├── layout.php
│ │ ├── error.php
│ │ ├── partials/
│ │ │ ├── header.php
│ │ │ └── footer.php
│ │ └── home/
│ │ └── index.php
│ │
│ ├── Route/
│ │ └── Router.php (routeur centralisé)
│ │ └── Routes.php (définition des routes)
│ │
│ └── Core/
│ ├── Controller.php
| ├── Database.php
│ └── View.php (moteur de rendu simplifié)
│ └── .htaccess (dossier inaccessible)
│
├── autoload.php
├── config.php
Cette structure est :
- claire, chaque fichier a sa place,
- modulaire, chaque brique peut évoluer indépendamment,
- sécurisée, grâce aux validations, headers et middlewares.
Créa-code a franchi une étape structurante. En mettant en place un routeur indépendant, un système de layout réutilisable, et une architecture modulaire prête à évoluer, nous avons jeté les bases d’une application professionnelle.
Mais surtout, cette transformation est restée simple, compréhensible et accessible aux débutants. Pas besoin d’un framework complet pour organiser proprement son projet PHP. Il suffit de comprendre les bonnes pratiques, et de les appliquer progressivement.
Voici le résumé complet et propre de l’ensemble des fichiers de notre architecture MVC pour le site code.crea-troyes.fr :
Les fichiers à la racine
autoload.php pour charger les class :
<?php
spl_autoload_register(function ($class) {
// On remplace le début du namespace par le chemin
$class = str_replace('App\\', 'app/', $class);
// On remplace les antislashs par des slashs
$class = str_replace('\\', '/', $class);
// On construit le chemin complet du fichier
$file = __DIR__ . '/' . $class . '.php';
// Si le fichier existe, on l’inclut
if (file_exists($file)) {
require_once $file;
} else {
echo "Fichier introuvable : $file";
}
});
config.php pour définir les constantes :
<?php
// Informations de connexion à la base de données (à adapter plus tard)
define('DB_HOST', 'localhost');
define('DB_NAME', 'creacode');
define('DB_USER', 'root');
define('DB_PASS', 'root');
define('BASE_URL', '/public/');
Le dossier public/
:
public/assets/css/styles.css qui contient notre feuille de style :
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
header, footer {
background: #f5f5f5;
padding: 1rem;
text-align: center;
}
nav a {
margin: 0 1rem;
text-decoration: none;
color: #333;
}
main.container {
padding: 2rem;
}
Pour en savoir plus sur ce que contient le dossier assets/, consultez notre tutoriel Le dossier asset en MVC.
Le fichier public/.htaccess pour gérer l’url-rewriting :
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
Le fichier public/index.php qui est la porte d’entrée du site pour l’ensemble des pages :
<?php
session_start();
require_once __DIR__ . '/../config.php';
require_once __DIR__ . '/../autoload.php';
require_once __DIR__ . '/../app/Route/Routes.php';
Dorénavant, on ne charge que les fichiers nécessaire qui eux chargeront les fichiers dont ils auront besoin. On démarre également un session PHP en prévision du futur.
Le dossier app/
Le fichier app/Controllers/HomeController.php qui est le contrôleur de notre page d’accueil et qui hérite de la class Controller.
<?php
namespace App\Controllers;
use App\Core\Controller;
use App\Core\View;
class HomeController extends Controller
{
public function index(): void
{
$title = "Accueil - Créa-code";
View::render('home/index', compact('title'));
}
}
Le fichier app/Core/Controller.php dont tous les contrôleurs hériteront. Pour l’instant cette class est vide mais, au fur et à mesure du développement, nous lui ajouterons différentes méthodes que l’ensemble des contrôleurs pourrons utiliser.
<?php
namespace App\Core;
class Controller
{
// Ce fichier est pour le moment vide
// Il servira plus tard de base commune pour vos futurs Controllers
}
Le fichier app/Core/Database.php qui nous permettra d’interagir avec notre base de données et nos tables.
<?php
namespace App\Core;
use PDO;
use PDOException;
class Database
{
private static $instance = null;
private $pdo;
private function __construct()
{
try {
$this->pdo = new PDO(
'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8',
DB_USER,
DB_PASS,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
]
);
} catch (PDOException $e) {
die('Erreur connexion base de données : ' . $e->getMessage());
}
}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new Database();
}
return self::$instance->pdo;
}
}
Le fichier app/Core/View.php dont toutes les vues hériteront. Pour l’instant cette class ne contient que la méthode render()
permettant d’inclure la vue correspondante et le layout.
<?php
namespace App\Core;
class View
{
public static function render(string $viewPath, array $data = []): void
{
extract($data); // Ex : $title, $content
ob_start();
require __DIR__ . '/../Views/' . $viewPath . '.php';
$content = ob_get_clean();
require __DIR__ . '/../Views/layout.php';
}
}
Le fichier app/Models/Model.php dont tous les Models hériteront. Pour l’instant cette class ne contient aucune méthode. Nous en ajouterons au fil du développement de Créa-code.
<?php
namespace App\Models;
class Model
{
// Ce fichier est pour le moment vide
// Il servira plus tard de base commune pour vos futurs modèles
}
Le fichier app/Route/Router.php qui est notre fichier le plus aboutis jusqu’à présent. incluant :
- Le système de routing avec paramètres dynamiques.
- Le système de middlewares intégré.
- La gestion des fichiers statiques (CSS, JS, images, etc.) pour qu’ils ne déclenchent pas de 404.
- Le nettoyage de l’URL.
<?php
namespace App\Route;
use App\Core\View;
class Router
{
protected $routes = [];
protected $middlewares = [];
protected $registeredMiddlewares = [];
public function get($path, $controllerMethod)
{
$path = trim($path, '/');
$this->routes['GET'][] = [
'path' => $path,
'controllerMethod' => $controllerMethod,
'middlewares' => []
];
return $this;
}
public function middleware(...$middlewares)
{
$lastIndex = array_key_last($this->routes['GET']);
foreach ($middlewares as $mw) {
$this->routes['GET'][$lastIndex]['middlewares'][] = $mw;
}
return $this;
}
public function registerMiddleware(string $name, callable $callback)
{
$this->registeredMiddlewares[$name] = $callback;
}
public function dispatch()
{
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
$basePath = '/public'; // Adapter si besoin
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
$path = parse_url($requestUri, PHP_URL_PATH);
// Retirer le chemin de base (si présent)
if (strpos($path, $basePath) === 0) {
$path = substr($path, strlen($basePath));
}
$url = trim($path, '/');
// Éviter d’intercepter les fichiers statiques (CSS, JS, images...)
$extension = pathinfo($url, PATHINFO_EXTENSION);
$staticExtensions = ['css', 'js', 'png', 'jpg', 'jpeg', 'gif', 'svg', 'ico', 'webp'];
if (in_array($extension, $staticExtensions)) {
return false; // Laisser Apache/Nginx ou le serveur PHP servir le fichier
}
if (!isset($this->routes[$method])) {
return $this->render404();
}
foreach ($this->routes[$method] as $route) {
// Gestion des routes dynamiques
$pattern = preg_replace('#\{[a-zA-Z0-9_]+\}#', '([a-zA-Z0-9_-]+)', $route['path']);
$pattern = '#^' . $pattern . '$#';
if (preg_match($pattern, $url, $matches)) {
array_shift($matches); // Supprimer l’URL complète de $matches
// Exécution des middlewares
foreach ($route['middlewares'] as $mwName) {
if (!isset($this->registeredMiddlewares[$mwName])) {
throw new \Exception("Middleware '$mwName' non enregistré.");
}
$result = call_user_func($this->registeredMiddlewares[$mwName]);
if ($result === false) {
return; // Middleware a bloqué l’accès
}
}
return $this->callController($route['controllerMethod'], $matches);
}
}
return $this->render404();
}
protected function callController(string $controllerMethod, array $params = [])
{
[$controllerName, $methodName] = explode('@', $controllerMethod);
$controllerClass = 'App\\Controllers\\' . $controllerName;
if (class_exists($controllerClass)) {
$controller = new $controllerClass();
if (method_exists($controller, $methodName)) {
return call_user_func_array([$controller, $methodName], $params);
}
}
return $this->render404();
}
protected function render404()
{
http_response_code(404);
return View::render('error', [], 'layout');
}
}
Le fichier app/Route/Routes.php où, comme son nom l’indique, nous définissons nos routes.
C’est ici que sont déclarés toutes nos routes, dans ce fichier unique
routes.php
. En faisant implicitement avec les appels à$router->get()
, nous n’avons pas besoin d’une liste blanche dans le routeur lui-même.
Ce fichier de routes = notre whitelist. Ça reste souple, maintenable, et plus intuitif.
<?php
use App\Route\Router;
$router = new Router();
// Enregistrement des middlewares
$router->registerMiddleware('auth', function () {
if (!isset($_SESSION['user'])) {
header('Location: /public/login');
return false;
}
return true;
});
$router->registerMiddleware('admin', function () {
if (!isset($_SESSION['user']) || $_SESSION['user']['role'] !== 'admin') {
http_response_code(403);
echo "Accès réservé aux administrateurs.";
return false;
}
return true;
});
// Routes
$router->get('', 'HomeController@index');
// $router->get('profil', 'UserController@profil')->middleware('auth');
// $router->get('admin/dashboard', 'AdminController@index')->middleware('auth', 'admin');
$router->dispatch();
Le fichier app/Views/layout.php contient et assemble les éléments récurrents à chacune des pages.
<?php
// Sécurité anti-XSS de base
function e(string $value): string {
return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
}
// Headers HTTP sécurisés
header('X-Frame-Options: DENY');
header('X-Content-Type-Options: nosniff');
header("Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'");
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title><?= e($title ?? 'Créa-code'); ?></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/css/styles.css">
</head>
<body>
<?php require_once __DIR__ . '/partials/header.php'; ?>
<main class="container">
<?= $content ?? ''; ?>
</main>
<?php require_once __DIR__ . '/partials/footer.php'; ?>
</body>
</html>
Le fichier app/Views/error.php contient la vue qui est appelé en cas d’erreur de routage. Erreur 404 y compris.
<h1>Error 404</h1>
Le fichier app/Views/home/index.php contient la vue de la page d’accueil.
<h1>Page d’accueil</h1>
<p>Bienvenue sur votre plateforme d'exercices de code en ligne.</p>
Les fichiers app/Views/partials/header.php et app/Views/partials/footer.php contiennent respectivement le header et le footer qui sera insérer sur chacune des pages grâce au layout.
<header>
<h1><a href="<?= BASE_URL ?>">Créa-code</a></h1>
<nav>
<a href="<?= BASE_URL ?>">Accueil</a>
</nav>
</header>
<footer>
<p>© <?= date('Y'); ?> Créa-code. Tous droits réservés.</p>
</footer>
Enfin, le fichier app/.htaccess empêche l’accès aux fichiers de l’application directement depuis leur url.
Deny from all
Aujourd’hui, le projet Créa-code franchit une nouvelle étape importante : la mise en place d’un routeur sécurisé. Ce routeur, cœur de l’architecture MVC, est désormais capable de gérer des routes dynamiques, de supporter des middlewares personnalisés (comme l’authentification ou l’autorisation admin), tout en distinguant intelligemment les fichiers statiques comme les feuilles de style ou les scripts JavaScript pour éviter les erreurs 404. La structure a été pensée pour rester simple à utiliser tout en offrant une base extensible et réutilisable dans l’ensemble du site.
En parallèle, nous avons renforcé l’aspect modulaire du projet en intégrant un système de layout global. Grâce à cette structure, les vues s’affichent désormais dans un gabarit commun incluant le header et le footer, ce qui rend l’affichage cohérent sur toutes les pages. Cette journée de développement aura permis de mieux comprendre les fondations d’une architecture MVC et de poser des bases solides pour l’organisation des routes, la protection des pages sensibles et la présentation uniforme du contenu.
Téléchargez cette architecture MVC en PHP au 13ème jour sur GitHub.
À demain pour la suite…