Voilà deux ans que je fais un cours, suivi d’un petit projet traitant du design Pattern MVC.  Le projet est à écrire en PHP5, avec une base de données MySQL comme support de stockage des données, l’architecture MVC est donc à implémenter dans un contexte purement web. Le paradigme objet est tout indiqué quand il s'agit d'écrire et d'agencer des composants logiciels, c'est donc celui qui sera adopté dans toute la suite.

Il y a bien entendu beaucoup de projets existants implémentant le design Pattern MVC en PHP, mais le propos du cours est plutôt de réaliser un cas pratique d’implémentation afin de bien saisir les bien faits du design pattern  MVC.

En effet l’utilisation d’un design pattern architectural en PHP, s’oppose à la pratique empirique de ce langage qui consiste à mélanger les connexions et accès à la base de données, avec le traitement des données et leur affichage. Dans ce cas il est alors commun d’avoir dans un seul script: du PHP, du SQL, du Javascript et du CSS dans les attributs des balises HTML soit pas moins de 5 langages distincts.

Au même titre qu’il est conseillé dans la présentation de séparer l’HTML, qui structure le document, du CSS, qui l’habille, il est conseillé d’utiliser un design pattern architectural pour structurer une application web.

Pour mémoire cette architecture permet d’organiser une application en 3 couches distinctes à savoir :

  • le modèle, qui contient la logique métier;

  • la vue, qui regroupe tout ce qui a trait à la présentation (des données / comme des interactions utilisateur);

  • le contrôleur, qui répond à des interactions utilisateurs en provenance de la vue, en appelant des traitements mis à disposition sous forme de méthode par le modèle, afin de nourrir la vue associée au traitement demandé par l'utilisateur.

MVC

Si vous pratiquez PHP et n'avez jamais utilisé le design pattern MVC, je vous recommande la lecture de : "comment convertir une application PHP standard en une application basée sur l’architecture MVC".

Le propos de ce billet n’est pas de vanter les mérites du design pattern MVC, car ils sont en général bien compris par mes étudiants. C'est plutôt d’en détailler la couche modèle dont la structure est assez dure à disséquer. J’ai moi-même pas mal lu et beaucoup débattu, avec le camarade will durand notamment, avant d'arriver à isoler chaque composant de cette couche.

Modèle

le Modèle

Sous sa forme la plus brute, la couche modèle peut être vu comme les « données ». Par données on entend tout ce qui est persistant, c'est-à-dire tout ce qu’on pourra lire à partir d’une source, et modifier pour le relire plus tard si besoin est. Dans une logique de découplage, il est de bon ton d’essayer de s’affranchir le plus possible de la forme brute des données. C’est ce que va faire le modèle en transformant des données brutes en objets structurés, utilisables simplement par la couche inférieure : le contrôleur.

Pour réaliser ce découplage le modèle utilise 3 couches d’abstraction :

  • La DAL (Data Access Layer) : couche abstraction de données
  • Le DAO (Data Access Object) : objet d’accès aux données
  • L’ORM (Object / Relation Mapping) : Mapping objet / relationnel
DAL

Pour l'exemple je vous propose de partir du diagramme UML suivant

UML

qui donne le MLD (schéma de base de données) suivant

MLD

La DAL

La DAL Permet de s’abstraire du support des données. Pour se faire elle met à disposition des méthodes génériques permettant d’accomplir des actions de maintenances sur les données. Les actions les plus communes sont regroupées sous l’acronyme CRUD (Create Read Update Delete). Basiquement la DAL va donc mettre à disposition des méthodes permettant d’ajouter, mettre à jour, lire, supprimer un enregistrement, et ce quelque soit le support de stockage des donnéees.

La généricité par rapport au stockage est en général matérialisée par un paramètre permettant de spécifier la nature du support (on appelle ça des drivers). Ainsi les méthodes CRUD associées au support de stockage sont utilisées de manière transparente par le développeur. Concrètement il n’y a donc en théorie qu’un paramètre à changer pour qu’une application utilisant une DAL puisse changer de support.

D’un point de vue strictement théorique la DAL devrait offrir la possibilité de maintenir des données dans n'importe quelle base de données, dans des fichiers texte, dans des fichiers xml …

D’un point de vue pratique, en PHP, une DAL utilise toujours un SGBD. Son rôle est donc de rendre l’applicatif qui l’utilise (la DAL) portable par rapport au SGBD utilisé.

Les DAL PHP que je connais sont Pear DB (la première que j'ai utilisé), Creole, et PDO qui tend à devenir le standard en PHP, puisque disponible sous forme d'extension PHP.

Le DAO

Le Dao a pour but de transformer les données contenues dans une bases de données en objets et inversement

Pour se faire il va faire correspondre (de manière bijective - ca veut dire qu'on peut rajouter "et inversement" à la fin de chacun des points suivants)

  • une table (appelée aussi relation) à une liste d’objets
  • une ligne d'une table (appelée aussi tuple) à un objet
  • un champs de base de données à un attribut d’objet
  • une valeur d’un champs à une valeur d’attribut d’un objet

Dans notre exemple les classes issues du DAO seront au minimum

UML DAO

je dis au minimum, car ces classes pourraient avoir un peu plus de ... classe! avec des getters et des setters.

Techniquement la DAO interroge le SGBD via la DAL sur la structure des tables afin de maintenir la correspondance entre les champs des tables de la base de données et les attributs des objets. Il y a au moins deux façons de réaliser celà:

Notez qu'à ce niveau là le seul code logique que possède les objets construits à partir d’un DAO sont les méthodes CRUD qui vont permettre d’aller le lire, le modifier, le supprimer en base. En cela les objets issus d’un DAO pourraient être appelés des POPO  (rigolez pas! c'est pas moi qui l'ai dit le premier) par analogie aux POJO Java (Plain Old Java Object)

Notez également que dans le schéma de présentation des couches d'abstraction du modèle,  le DAO utilise la DAL, mais que ce n’est pas une vraie obligation : un DAO hardcodé en mysql resterait un DAO … simplement non portable au niveau du SGBD.

Notez enfin que chaque classe est isolée, c'est à dire qu'il n'existe pas de code logique qui permette une quelconque interaction entre elles.

L’ORM

L’ORM a pour but de transformer les relations entre les tables d’ une base de données en relations entre objets et inversement

Elle va typiquement se préoccuper de matérialiser les clés étrangères par des dépendances entre objets

UML ORM

L'intérêt réside dans le fait que les méthodes de la couche ORM, renvoient ou prennent en paramètres des listes d'objets. Par exemple \$post->getComments() renverra une liste d'objets de classe Comment. Ces objets Comment seront sous forme de POPOS, c'est en celà que l'ORM utilise le DAO.

Techniquement l’ORM utilise soit les contraintes d’intégrité référentielle, soit une certaine logique de nommage, pour déterminer les clés étrangères. Dans les deux cas elle passe par la DAL.

Comme pour le DAO, les stratégies de génération de code ou d'utilisation des méthodes magiques peuvent être adoptées.

Comme pour le DAO également, l'utilisation d'une DAL est conseillée mais pas obligatoire.

propel et doctrine sont deux ORM PHP typiques.

La couche métier

Le but des couhes précédentes est de soulager la couche métier. Si la couche métier peut hériter des méthodes de la DAO et de l'ORM, nous aurons des objets présentant toutes les méthodes pour les gérer en base.

UML METIER

La couche métier est sensée ne contenir que la logique métier, c'est à dire propre à l'objet qu'elle représente. Ce sera effectivement le cas dans la class Post par exemple, où l'on pourra n'avoir qu'une seule méthode Post::getArchives(), qui retourne une liste de liste contenant les archives du type

Array(
'2009' => Array('janvier' => 1),
'2008' => Array('septembre' => 7, 'octobre' => 2, 'novembre' => 1, 'décembre' => 1)
)

Cette méthode fait bien parti de la couche métier puisqu'elle est propre au concept de post (ou billet) de blog.

En appelant cette méthode le contrôleur pourra nourrir une vue qui n'aura alors qu'un double foreach à faire pour présenter les archives dans le menu de droite.

conclusion

Les concepts que je viens de détailler sont souvent amalgamés, aussi il est souvent difficile de les cerner précisément. J'ai essayé d'illustrer le rôle de chacun par un exemple simpliste, mais je ne prétends détenir aucune vérité sur le sujet et les commentaires sont ouverts pour accueillir vos questions, suggestions et corrections

le mld a été généré avec DBDesigner4 et tout les diagrammes uml ont été générés avec yUML


Commentaires

comments powered by Disqus