Les Design Patterns - Partie 1 : MVC¶§
- Réponses à des problématiques de conception récurrentes
- Ensemble de bonne pratiques
Le Pattern MVC¶§
MVC : Model View Controller¶§
- Architecture applicative
- Façon d’organiser le code
- Consiste à découper le code en séparant:
- Une partie modèle
- Une partie vue
- Une partie controlleur
- Utilisée par de nombreux frameworks PHP (Symfony 2 etc...)
Note
Framework : Ensemble de composants qui servent à créer les fondations, l’architecture et les grandes lignes d’un logiciel
La partie Modèle¶§
Logique métier
C’est la problématique traitement/calcul
Elle contient aussi tout ce qui concerne l’accès aux données
C’est là qu’on trouvera les requêtes SQL
En Web, on utilise souvent la notion d’ ORM : Object Relational Mapper
Il s’agit de mapper les tables SQL avec des classes de deux types :
- Les objets qu’on manipule, les DTO, Data Transfer Object
- Une classe pour chaque table sur laquelle on souhaite travailler
- Les colonnes des tables deviennent des attributs d’objets
- Ce sont des objets très simples (uniquement les colonnes de la table, et des accesseurs)
- Les objets qui font le lien avec la base de données, les Repository (aussi appelés DAO, Data Access Object)
- Une classe par table également
- Ce sont les objets qui font les requêtes
- Ils ont une référence vers la BDD (PDO)
- Une méthode
getById($id)
pour créer un objet DTO et remplir ses attributs à partir de la base, grâce à une requête SQL (on appelle ça “hydrater” le DTO) - Une méthode par cas d’utilisation (tous les films sortis en 2009, tous les films avec Di Caprio...)
- ces méthodes retournent une collection (array par exemple) de DTO hydratés
persist($dto)
pour sauvegarder un nouveau DTO en base (puis penser à hydrater son ID, voir PDO::lastInsertId())update($dto)
pour enregistrer en base les modifications faites sur un DTO existant (hydraté)delete($dto)
pour supprimer de la base un DTO existant (hydraté)
La partie contrôleur¶§
- Lien entre l’utilisateur et le reste de l’application
- Elle se charge d’analyser et de traiter la requête de l’utilisateur.
- Elle demande au modèle les données (DTOs, collections de DTOs) et passe la main à la vue qui utilisera ces données pour afficher la page
- En Web, il y a souvent un FrontController (index.php) qui analyse la requête HTTP et dispatche vers le sous-contrôleur de la page demandée
- Il faut que toutes les requêtes arrivent vers le FrontController quelque soit l’URL demandée
- Utilisation du .htaccess
$_SERVER['REQUEST_URI']
La partie Vue¶§
- Affichage
- C’est la problématique présentation
- C’est l’unique endroit où on aura du HTML
- Un tout petit peu de PHP très succint. Pour être lisible au sein du HTML on évite les accolades et on préfère la syntaxe courte :
- affichages avec
<?=
et?>
- conditions avec
<?php if (cond): ?>
,<?php elseif (cond): ?>
,<?php else: ?>
, et<?php endif ?>
- boucles sur des collections avec
<?php foreach ($collection as $item): ?>
et<?php endforeach ?>
- affichages avec
- C’est le designer qui travaille la vue (d’où l’intérêt de garder le code PHP très simple)
- Il existe des moteurs de template comme par exemple twig
Avantages de MVC¶§
- Séparation des préoccupations
- Code clair, bien organisé, gage de réutilisabilité
- Découpage standard qui permet aux autres développeurs de rapidement rentrer dans votre code
- Découpage des responsabilités qui permet à des développeurs avec différents profils de travailler sur un projet
Projet v2¶§
Vers MVC Maison¶§
Transformer son code en une architecture MVC Maison
Arborescence à respecter : 3 répertoires “Model”, “View”, “Controller” ; un index.php qui sert de FrontController, et un répertoire “Library” pour stocker les bibliothèques additionnelles si nécessaire.
- Refactoriser le code concernant l’accès aux données pour votre projet en créant/reprenant les classes suivantes:
- Film (représentation d’un film de la table Film)
- FilmRepository (contient les méthodes d’hydratation, persistence, mise à jour, suppression)
- Actor
- ActorRepository
- Casting
- CastingRepository
- DBConnectionManager
Exemple de Repositories
FilmRepository - bdd : PDO + getById(int) : Film + getByYear(int) : Film[] + persist(Film) + update(Film) + delete(Film) + getFilmsWith(Actor) : Film[]
NB : getFilmsWith(Actor) fera une jointure sur Casting. En effet un Repository a le droit de requêter une table en rapport avec sa table “de prédilection”
ActorRepository - bdd : PDO ... même modèle que pour Film + getActorsIn(Film) : Actor[]
Idem : getActorsIn(Film) fera une jointure sur Casting.
CastingRepository - bdd : PDO + getBy(Actor, Film) : Casting + persist(Casting) + update(Casting) + delete(Casting)
- Refactoriser le reste du code concernant la vue de l’itération 1 :
- Créer un fichier layout.php (à placer dans le dossier View) contenant tous les éléments communs des vues. Il constue donc un modèle de page (template). Il permet également d’ajouter les éléments spécifiques à chaque vue à l’aide de deux variables $title et $content (la variable $content pourra etre remplie grace à la bufferisation de sortie)
<!DOCTYPE html> <html lang="fr"> <head> <title><?= $title ?></title> </head> <body> <?= $content ?> </body> </html>
- Les éléments communs de votre design (menu, boutons, formulaires) devront également etre rajoutés (ou inclus) dans cette page
- Sans paramètres, le FrontController
index.php
enverra vers un sous-contrôleur par défaut qui listera tous les films.
- On souhaite que l’utilisateur puisse accéder au détail d’un film (en particulier le casting de celui-ci).
- La page /detailFilm?id=<ID> devra permettre d’afficher les informations relatives à film, ainsi que son casting, avec les acteurs ordonnés par rang de casting en conservant la charte graphique adoptée.
- Le FrontController doit regarder l’URL et dispatcher vers le contrôleur de detailFilm
- Modifier l’affichage des films pour y rajouter pour chacun un lien vers le détail de ce film
- Inclure un lien accueil pour retourner à la liste des films