Semaine 4 - Jour 4 : Introduction au Pattern MVC

Aujourd'hui, nous découvrons le pattern MVC (Modèle-Vue-Contrôleur), une architecture logicielle qui sépare les responsabilités de notre application en trois composants distincts.

1. Qu'est-ce que le pattern MVC ?

Modèle-Vue-Contrôleur

Modèle (Model)

Rôle : Gère les données et la logique métier

  • Accès à la base de données
  • Validation des données
  • Logique métier

Vue (View)

Rôle : Affiche les données

  • HTML, CSS
  • Présentation visuelle
  • Interface utilisateur

Contrôleur (Controller)

Rôle : Fait le lien entre Modèle et Vue

  • Reçoit les requêtes
  • Appelle le Modèle
  • Passe les données à la Vue

Flux d'une requête MVC

1. L'utilisateur visite : index.php?action=show&id=1 2. Le Contrôleur reçoit la requête → Quelle action ? show → Quel ID ? 1 3. Le Contrôleur appelle le Modèle → "Donne-moi l'article avec l'ID 1" 4. Le Modèle interroge la base de données → SELECT * FROM articles WHERE id = 1 5. Le Modèle retourne les données au Contrôleur → ["id" => 1, "titre" => "Mon article", "contenu" => "..."] 6. Le Contrôleur passe les données à la Vue → "Affiche cet article" 7. La Vue génère le HTML → <h1>Mon article</h1><p>...</p> 8. L'utilisateur voit la page HTML

Avantages du MVC :

  • Séparation des responsabilités : Chaque partie a un rôle clair
  • Maintenabilité : Facile de modifier une partie sans casser les autres
  • Réutilisabilité : Un même Modèle peut servir plusieurs Vues
  • Travail en équipe : Design (Vue), Back-end (Modèle), Logique (Contrôleur)

2. Structure des dossiers MVC

Organisation recommandée

projet-mvc/ │ ├── public/ │ └── index.php // Point d'entrée unique │ ├── src/ │ ├── Controllers/ │ │ ├── HomeController.php │ │ └── ArticleController.php │ │ │ ├── Models/ │ │ ├── Article.php │ │ └── User.php │ │ │ └── Views/ │ ├── home/ │ │ └── index.php │ ├── articles/ │ │ ├── list.php │ │ └── show.php │ └── layout/ │ ├── header.php │ └── footer.php │ ├── config/ │ └── database.php // Configuration BDD │ └── autoload.php // Autoloader

3. Le Modèle (Model)

Exemple : Modèle Article

<?php // src/Models/Article.php namespace Models; class Article { private $pdo; public function __construct($pdo) { $this->pdo = $pdo; } // Récupérer tous les articles public function getAll() { $sql = "SELECT * FROM articles ORDER BY date_creation DESC"; $stmt = $this->pdo->query($sql); return $stmt->fetchAll(\PDO::FETCH_ASSOC); } // Récupérer un article par son ID public function getById($id) { $sql = "SELECT * FROM articles WHERE id = :id"; $stmt = $this->pdo->prepare($sql); $stmt->execute(['id' => $id]); return $stmt->fetch(\PDO::FETCH_ASSOC); } // Créer un nouvel article public function create($titre, $contenu, $auteur) { $sql = "INSERT INTO articles (titre, contenu, auteur, date_creation) VALUES (:titre, :contenu, :auteur, NOW())"; $stmt = $this->pdo->prepare($sql); $stmt->execute([ 'titre' => $titre, 'contenu' => $contenu, 'auteur' => $auteur ]); return $this->pdo->lastInsertId(); } // Mettre à jour un article public function update($id, $titre, $contenu) { $sql = "UPDATE articles SET titre = :titre, contenu = :contenu WHERE id = :id"; $stmt = $this->pdo->prepare($sql); return $stmt->execute([ 'id' => $id, 'titre' => $titre, 'contenu' => $contenu ]); } // Supprimer un article public function delete($id) { $sql = "DELETE FROM articles WHERE id = :id"; $stmt = $this->pdo->prepare($sql); return $stmt->execute(['id' => $id]); } } ?>

4. Le Contrôleur (Controller)

Exemple : Contrôleur Article

<?php // src/Controllers/ArticleController.php namespace Controllers; use Models\Article; class ArticleController { private $articleModel; public function __construct($pdo) { $this->articleModel = new Article($pdo); } // Action : Afficher la liste des articles public function index() { // 1. Récupérer les données du Modèle $articles = $this->articleModel->getAll(); // 2. Passer les données à la Vue require __DIR__ . '/../Views/articles/list.php'; } // Action : Afficher un article public function show($id) { // 1. Récupérer l'article $article = $this->articleModel->getById($id); // 2. Vérifier si l'article existe if (!$article) { die("Article non trouvé"); } // 3. Afficher la Vue require __DIR__ . '/../Views/articles/show.php'; } // Action : Créer un article public function create() { if ($_SERVER['REQUEST_METHOD'] === 'POST') { $titre = trim($_POST['titre'] ?? ''); $contenu = trim($_POST['contenu'] ?? ''); $auteur = trim($_POST['auteur'] ?? ''); if (!empty($titre) && !empty($contenu) && !empty($auteur)) { $id = $this->articleModel->create($titre, $contenu, $auteur); header("Location: index.php?action=show&id=$id"); exit(); } } require __DIR__ . '/../Views/articles/create.php'; } // Action : Supprimer un article public function delete($id) { $this->articleModel->delete($id); header("Location: index.php?action=index"); exit(); } } ?>

5. La Vue (View)

Exemple : Vue Liste des articles

<?php // src/Views/articles/list.php ?> <!DOCTYPE html> <html> <head> <title>Liste des articles</title> </head> <body> <h1>Liste des articles</h1> <a href="index.php?action=create">Créer un article</a> <?php foreach ($articles as $article): ?> <div> <h2> <a href="index.php?action=show&id=<?php echo $article['id']; ?>"> <?php echo htmlspecialchars($article['titre']); ?> </a> </h2> <p><?php echo nl2br(htmlspecialchars(substr($article['contenu'], 0, 200))); ?>...</p> </div> <?php endforeach; ?> </body> </html>

Exemple : Vue Article détaillé

<?php // src/Views/articles/show.php ?> <!DOCTYPE html> <html> <head> <title><?php echo htmlspecialchars($article['titre']); ?></title> </head> <body> <a href="index.php?action=index">← Retour à la liste</a> <h1><?php echo htmlspecialchars($article['titre']); ?></h1> <p> <strong>Auteur :</strong> <?php echo htmlspecialchars($article['auteur']); ?><br> <strong>Date :</strong> <?php echo date('d/m/Y', strtotime($article['date_creation'])); ?> </p> <div> <?php echo nl2br(htmlspecialchars($article['contenu'])); ?> </div> <a href="index.php?action=delete&id=<?php echo $article['id']; ?>" onclick="return confirm('Supprimer cet article ?')">Supprimer</a> </body> </html>

6. Routing simple avec $_GET

Point d'entrée : index.php

<?php // public/index.php - Point d'entrée unique require_once __DIR__ . '/../autoload.php'; require_once __DIR__ . '/../config/database.php'; use Controllers\ArticleController; use Controllers\HomeController; $action = $_GET['action'] ?? 'home'; $id = $_GET['id'] ?? null; try { switch ($action) { case 'home': $controller = new HomeController(); $controller->index(); break; case 'index': $controller = new ArticleController($pdo); $controller->index(); break; case 'show': if ($id) { $controller = new ArticleController($pdo); $controller->show($id); } break; default: die("Action inconnue"); } } catch (\Exception $e) { error_log($e->getMessage()); die("Une erreur s'est produite"); } ?>

Exemples d'URLs

URL Contrôleur Action Description
index.php HomeController index() Page d'accueil
index.php?action=index ArticleController index() Liste des articles
index.php?action=show&id=1 ArticleController show(1) Article détaillé
index.php?action=create ArticleController create() Créer un article
Froggiesplaining :


Objectifs de ce cours :
✅ Comprendre le pattern MVC (Modèle-Vue-Contrôleur)
✅ Organiser un projet avec une structure MVC claire
✅ Créer des Modèles pour gérer les données (CRUD)
✅ Créer des Contrôleurs pour orchestrer la logique
✅ Créer des Vues pour afficher les données
✅ Implémenter un système de routing simple

Points clés à retenir :
Modèle = Ma réserve de mouches (base de données, getAll(), getById())
Vue = Mon miroir d'eau (HTML/CSS, affichage uniquement)
Contrôleur = Moi qui décide (reçoit requête, appelle Modèle, passe à Vue)
Routing = Panneau de signalisation (?action=show&id=5)
Flux MVC = User → Router → Controller → Model → Controller → View → User
Séparation des responsabilités = Modèle ne fait pas de HTML, Vue ne fait pas de SQL
• Structure: src/Models/, src/Controllers/, src/Views/
• Point d'entrée unique: public/index.php

Exercice pratique :
1. Créer la structure MVC complète (Models, Controllers, Views)
2. Créer Models\Article.php avec getAll(), getById(), create(), update(), delete()
3. Créer Controllers\ArticleController.php avec index(), show(), create()
4. Créer Views\articles\index.php pour lister les articles
5. Créer Views\articles\show.php pour afficher un article détaillé
6. Créer public\index.php avec switch sur $_GET['action']
7. Tester: index.php?action=index puis index.php?action=show&id=1
8. Conseil de Froggie: Respecte les responsabilités ! Le Modèle ne fait pas de HTML, la Vue ne fait pas de SQL. Chacun sa mare !

Froggie explain

GitHub - eCrea