À propos de cette démo
Du MVC scolaire à l'architecture web professionnelle
Du MVC scolaire à l'architecture web professionnelle
💡 Professionnel signifie : compréhensible, testable, extensible,
structure sécurisée
Développement d'un mini-framework modulaire comme base de projet à long terme
Objectif
Ce projet sert de référence architecturale pour le développement d'applications web évolutives. Il montre la transition progressive d'une structure MVC scolaire vers une architecture web professionnelle et modulaire.
Le résultat final n'est pas un projet unique, mais un mini-framework léger qui :
- Est compréhensible, testable, extensible et structure sécurisée.
- Sert de base stable pour n'importe quel projet web
- Évite les refontes complètes ultérieures
«Construire le bon châssis une fois – puis échanger seulement les modules.»
Point de départ
Plusieurs projets de démonstration déjà réalisés servent de base (notamment MVC, Sessions, Login, CSS modulaire).
Ces projets sont fonctionnellement bien construits, mais reposent fortement sur des fonctions et sont principalement adaptés aux applications plus petites. Avec l'augmentation de la taille du projet, ils atteignent leurs limites en termes de structure, maintenabilité et extensibilité.
Pour contrôler cette transition, j'ai créé 2 projets, on pourrait dire en 2 phases :
- Phase 1: Amélioration d'un projet MVC scolaire classique
- Phase 2: Professionnalisation de mon projet de démo de connexion et passage au niveau supérieur.
Étapes
👉 Chaque étape fonctionne indépendamment
👉 Pas de moments de "tout recommencer"
| ÉTAPE | FOCUS | OBJECTIF | PHASE |
|---|---|---|---|
| 1 | MVC Scolaire | Compréhension (point de départ) | 1 |
| 2 | Structure de dossiers & Service | Séparer les responsabilités & Vue d'ensemble | 1 |
| 3 | Allégement de l'index & Flux de requêtes | Bootstrap & Routeur | 1 |
| 4 | Configuration .htaccess | Sécurité d'accès (base) | 1 |
| 5 | Ajustements pour la Phase 2 | Modularité & Maintenabilité | 2 |
| 6 | CSS Modulaire | Maintenabilité & Évolutivité | 2 |
| 7 | Classes & Navigation | Structure & Testabilité | 2 |
| 8 | Mini-Framework | Base à long terme | 2 |
Le tableau montre la transition structurée des concepts simples vers l'architecture professionnelle.
Structure
Objectif: Séparer les responsabilités, sécurité et clarté, sans refonte
Principe: Seul public/ est accessible publiquement – tout le reste est protégé.
10_Professional_web/ ├─ app/ │ ├─ config/ │ ├─ control/ │ ├─ helper/ │ ├─ model/ │ ├─ router/ │ ├─ security/ │ ├─ service/ │ ├─ view/ │ └─ bootstrap.php │ └─ router.php │ └─ session.php ├─ doc/... ├─ public/ ← seul public │ ├─ css/ │ └─ img/ │ ├─ js/ │ ├─ index.php ← Point d'entrée unique ├─ sql/ ├─ storage/ │ ├─ logs/ │ └─ upload/ └─ README.md
Allégement de l'index
Problème
Dans le MVC scolaire, index.php assume trop de tâches :
- Routeur
- Contrôleur
- Porte de sécurité
- Orchestrateur de flux de travail
👉 Point unique de chaos
Objectif
index.php devient
- Point de départ
- aucune logique
Solution
- Externaliser le routeur
- Logique Bootstrap centrale
- Préparation pour l'autochargement
- Pipeline de requêtes claire
Pipeline de requêtes
Requête ↓ public/index.php ↓ Bootstrap ↓ Routeur ↓ Contrôleur ↓ Service ↓ Vue / Réponse
Bootstrap
Initialise :
- Config
- Session
- Helper
- Contrôleur & Service
- Modèle & Vue
Routeur
Tâche :
- URL → Contrôleur / Action
- Extraire les paramètres
- Traiter les erreurs proprement
Mettre en œuvre
- Créer : app/bootstrap.php
- Déplacer les chemins d'importation de l'index vers le nouveau bootstrap
- Déplacer le switch($page) dans le contrôleur dans une fonction intégrée.
- Déplacer le contenu du contrôleur dans le dossier Service et le répartir sur les nouveaux fichiers :
App/services/ │ ├─ AuthService.php │ ├─ UserService.php │ ├─ ProfileService.php │ ├─ SessionService.php │ └─ UploadService.php
- Créer : app/router.php
- Déplacer la vérification de langue et de page de session.php vers router.php
Accès sécurisé avec .htaccess
Architecture à deux fichiers
Pour le contrôle d'accès, une architecture à deux fichiers avec .htaccess est utilisée. Le fichier dans le répertoire racine contrôle l'accès externe et dirige les demandes spécifiquement vers le dossier public. Le .htaccess dans le répertoire public prend en charge le routage d'application.
Cette séparation assure un concept de sécurité multicouche, des responsabilités claires et une meilleure maintenabilité.
Ajustements pour la Phase 2
La Phase 2 sert à préparer l'architecture existante de manière ciblée à la croissance, à la complexité croissante et à la gestion propre des ressources.
Répartition de la configuration
app/config/ ├── config.php # Configuration principale ├── app/ # Configuration d'application │ ├── form.config.php # Configurations de formulaire │ └── app.config.php # Paramètres de l'app └── domain/ # Configs spécifiques au domaine │ ├── page.config.php # Configuration des pages │ └── user.config.php # Config gestion des utilisateurs └── security/ # Espace réservé pour la sécurité
- 🎯 Chargement ciblé : Seulement les configurations nécessaires chargées
- 📁 Meilleure organisation : Regroupement thématique
- 🧩 Modularité : Intégration facile dans les services
CSS Modulaire
Dans l'étape suivante, le CSS modulaire a été intégré au projet. Un projet de démonstration existant a servi de base, pouvant être repris avec peu d'effort et inséré dans le répertoire app/css/. La structure existante a ensuite été légèrement adaptée et optimisée pour s'intégrer proprement dans le reste de l'architecture.
Pour intégrer professionnellement le CSS modulaire dans l'application, les styles ne sont pas livrés directement depuis la zone App. Au lieu de cela, le CSS est généré dynamiquement dans le répertoire public/css/. Ainsi, il peut être inclus dans l'en-tête comme une feuille de style classique :
<link rel="stylesheet" href="css/style.php?page=<?php echo htmlspecialchars($_SESSION[S_PAGE]); ?>">
Le fichier style.php sert de point d'entrée contrôlé. Il intègre les modules CSS internes, empêche l'accès direct aux fichiers internes et garantit que le CSS est correctement livré comme feuille de style. De plus, la mise en cache indésirable est empêchée, de sorte que les modifications prennent effet immédiatement :
// Définir une constante de sécurité pour empêcher l'accès direct aux fichiers include
define("SECURE_INCLUDE", true);
// Inclure le fichier CSS principal
require_once __DIR__ . "/../../app/css/main.css.php";
// Déclarer le fichier comme CSS et empêcher le cache
header("Content-Type: text/css; charset=UTF-8");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache");
header("X-Content-Type-Options: nosniff");
// Déterminer la page via paramètre GET
$page = $_GET["page"] ?? "index";
if (!in_array($page, P_LIST, true)) {
$page = "index";
}
echo generateCSS(renderCSS($page));Cette solution combine les avantages du CSS modulaire avec une séparation claire entre la structure interne et la livraison publique et s'intègre parfaitement dans l'architecture de projet existante.
Classes
Les classes sont utilisées dans le projet là où elles apportent une valeur ajoutée claire. Cela inclut les données partagées avec leur logique, les dépendances plus complexes ainsi que les domaines où la testabilité et l'extensibilité sont importantes. Toutes les fonctions ne sont pas nécessairement converties en classe.
Les vues restent de simples templates, et les helpers simples peuvent délibérément rester des fonctions.
Session
La logique de session a été entièrement externalisée dans sa propre classe. Pour cela, la classe cSession a été créée, qui prend en charge le démarrage et l'initialisation de base de la session de manière centrale :
class cSession {
public static function start(): void {
session_start();
self::initDefaults();
self::initCsrfToken();
self::sanitizeSession();
}
// et ces fonctions créées :
initDefaults
initCsrfToken
sanitizeSession
requireAccess
isGuest
getRole
getUserId
increaseLoginAttempts
isRateLimited
La fonction check_user_access a été retirée de la classe Session et déplacée vers AuthService. La vérification des rôles au début de la session a également été externalisée vers la zone d'authentification, regroupée dans la fonction auth_init et appelée de manière centrale dans le Bootstrap.
En outre, un AdminService a été introduit. La vérification de l'utilisateur pouvant être modifié a été retirée de la session et encapsulée dans sa propre fonction set_edit_user_id, qui est également exécutée au démarrage dans le Bootstrap.
Dans le cadre de la restructuration, les appels de fonctions ont été uniformisés, par exemple de handleSessionTimer() à cSession::increaseLoginAttempts() ainsi que de isSessionLimited() à isRateLimited(). Enfin, les fichiers obsolètes ont été supprimés, concrètement session.php dans le répertoire app ainsi que session_service.php dans la zone Service.
Routeur
Le routeur a également été externalisé dans sa propre classe. La classe cRouter prend en charge l'initialisation centrale du routage et s'occupe de la reconnaissance de la langue et de la page :
class cRouter {
public static function init(): void {
self::resolveLanguage();
self::resolvePage();
}
}La logique précédente de reconnaissance de la langue et de la page a été retirée du contexte Session et transférée dans deux fonctions clairement séparées au sein du routeur. Ainsi, la responsabilité du routage incombe entièrement au routeur, tandis que la classe Session se concentre sur ses tâches propres.
Base de données
Pour la connexion à la base de données, une classe générale a été créée, qui regroupe les tâches récurrentes et simplifie l'interaction avec la base de données. La classe cDatabase encapsule l'établissement de la connexion ainsi que les opérations de requête et d'exécution fréquemment nécessaires :
class cDatabase {
private static ?PDO $dbh = null;
public static function getConnection(): PDO {…}
public static function close(): void {…}
public static function fetchAll(…): array {… }
public static function fetchOne(…): array|false {…}
public static function execute(…): bool {…}
}Grâce à cette abstraction centrale, les accès à la base de données sont mis en œuvre de manière uniforme et les fonctions existantes sont simplifiées, car la logique récurrente n'est plus implémentée qu'une seule fois. Des approches de cohérence supplémentaires améliorent la maintenabilité, réduisent les sources d'erreurs et forment une base stable pour les extensions.
Mini-Framework
En combinant les concepts précédemment introduits, un mini-framework
léger émerge du projet MVC original.
Bootstrap, Routeur, règles de sécurité centrales, couche Service, configuration
modulaire ainsi que des responsabilités clairement séparées forment ensemble
une architecture stable.
Ce mini-framework ne remplace pas complètement les grands frameworks,
mais sert de base contrôlée et compréhensible pour vos propres projets web.
Il permet des extensions propres, évite les ruptures structurelles ultérieures
et permet de nouvelles applications sur une base éprouvée.
👉 Le projet ne se termine pas avec une application unique, mais avec une architecture réutilisable.