Documente Academic
Documente Profesional
Documente Cultură
Dcouvrez comment amliorer l'architecture d'un site Web, depuis une organisation
classique vers une architecture MVC utilisant un framework cr de toutes pices.
Cet article est une adaptation d'un cours donn aux tudiants de seconde anne de BTS
SIO (Services Informatiques aux Organisations) au lyce La Martinire Duchre de Lyon.
Tous les fichiers source sont disponibles sur le dpt GitHub associ l'article.
IMPORTANT : cet article est vise uniquement pdagogique. Le framework construit ici
illustre certains principes de conception logicielle mais n'est pas destin une utilisation
professionnelle. Si vous souhaitez dcouvrir comment intgrer un vrai framework PHP
vos dveloppements, consultez ce cours.
Commentez
voluer vers une architecture MVC en PHP par Baptiste Pesquet
-2-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
VII - Remerciements.................................................................................................................................................. 50
-3-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Nous mettrons en uvre les principes prsents dans cet article sur un exemple simple : une page Web PHP de
type blog puisant ses informations dans une base de donnes relationnelle.
La base de donnes utilise est trs simple. Elle se compose de deux tables, l'une stockant les billets (articles) du
blog et l'autre les commentaires associs aux articles.
Cette base de donnes contient quelques donnes de test, insres par le script SQL ci-dessous.
index.php
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="style.css" />
<title>Mon Blog</title>
</head>
<body>
<div id="global">
<header>
<a href="index.php"><h1 id="titreBlog">Mon Blog</h1></a>
<p>Je vous souhaite la bienvenue sur ce modeste blog.</p>
</header>
<div id="contenu">
-4-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
index.php
<?php
$bdd = new PDO('mysql:host=localhost;dbname=monblog;charset=utf8',
'root', '');
$billets = $bdd->query('select BIL_ID as id, BIL_DATE as date,'
. ' BIL_TITRE as titre, BIL_CONTENU as contenu from T_BILLET'
. ' order by BIL_ID desc');
foreach ($billets as $billet): ?>
<article>
<header>
<h1 class="titreBillet"><?= $billet['titre'] ?></h1>
<time><?= $billet['date'] ?></time>
</header>
<p><?= $billet['contenu'] ?></p>
</article>
<hr />
<?php endforeach; ?>
</div> <!-- #contenu -->
<footer id="piedBlog">
Blog ralis avec PHP, HTML5 et CSS.
</footer>
</div> <!-- #global -->
</body>
</html>
cette page est crite en HTML5 et utilise certaines nouvelles balises, comme <article> ;
elle emploie l'affichage abrg <?= ?> plutt que <?php echo ?>, ainsi que la syntaxe alternative
pour la boucle foreach ;
elle utilise l'extension PDO de PHP afin d'interagir avec la base de donnes.
Pour le reste, il s'agit d'un exemple assez classique d'utilisation de PHP pour construire une page dynamique affiche
par le navigateur client.
Une feuille de style CSS est utilise afin d'amliorer le rendu HTML. Voici le code source associ.
style.css
/* Pour pouvoir utiliser une hauteur (height) ou une hauteur minimale
(min-height) sur un bloc, il faut que son parent direct ait lui-mme une
hauteur dtermine (donc toute valeur de height sauf "auto": hauteur en
pixels, em, autres units...).
Si la hauteur du parent est en pourcentage, elle se rfre alors la
hauteur du grand-pre, et ainsi de suite.
Pour pouvoir utiliser un "min-height: 100%" sur div#global, il nous faut:
- un parent (body) en "height: 100%";
- le parent de body galement en "height: 100%". */
html, body {
height: 100%;
}
body {
color: #bfbfbf;
background: black;
font-family: 'Futura-Medium', 'Futura', 'Trebuchet MS', sans-serif;
}
h1 {
color: white;
}
.titreBillet {
margin-bottom : 0px;
}
-5-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
style.css
#global {
min-height: 100%; /* Voir commentaire sur html et body plus haut */
background: #333534;
width: 70%;
margin: auto; /* Permet de centrer la div */
text-align: justify;
padding: 5px 20px;
}
#contenu {
margin-bottom : 30px;
}
#titreBlog, #piedBlog {
text-align: center;
}
-6-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
interactions avec l'extrieur, en particulier l'utilisateur : saisie et contrle de donnes, affichage. C'est la
problmatique de prsentation ;
oprations sur les donnes (calculs) en rapport avec les rgles mtier ( business logic ). C'est la
problmatique des traitements ;
accs et stockage des informations qu'il manipule, notamment entre deux utilisations. C'est la problmatique
des donnes.
La page Web actuelle mlange code de prsentation (les balises HTML) et accs aux donnes (requtes SQL). Ceci
est contraire au principe de responsabilit unique. Ce principe de conception logicielle est le suivant : afin de
clarifier l'architecture et de faciliter les volutions, une application bien conue doit tre dcompose en sous-parties,
chacune ayant un rle et une responsabilit particuliers. L'architecture actuelle montre ses limites ds que le contexte
se complexifie. Le volume de code des pages PHP explose et la maintenabilit devient dlicate. Il faut faire mieux.
Une premire amlioration consiste sparer le code d'accs aux donnes du code de prsentation au sein du
fichier index.php.
index.php
<?php
// Accs aux donnes
$bdd = new PDO('mysql:host=localhost;dbname=monblog;charset=utf8', 'root', '');
$billets = $bdd->query('select BIL_ID as id, BIL_DATE as date,'
. ' BIL_TITRE as titre, BIL_CONTENU as contenu from T_BILLET'
. ' order by BIL_ID desc');
?>
-7-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Le code est devenu plus lisible, mais les problmatiques de prsentation et d'accs aux donnes sont toujours
gres au sein d'un mme fichier PHP. En plus de limiter la modularit, ceci est contraire aux bonnes pratiques de
dveloppement PHP (norme PSR-1).
On peut aller plus loin dans le dcouplage en regroupant le code d'affichage prcdent dans un fichier ddi nomm
vueAccueil.php.
vueAccueil.php
<!doctype html>
<html lang="fr">
<head>
...
</head>
<body>
...
<div id="contenu">
<?php foreach ($billets as $billet): ?>
<article>
...
</article>
<hr />
<?php endforeach; ?>
</div> <!-- #contenu -->
...
</body>
</html>
index.php
<?php
// Accs aux donnes
$bdd = new PDO('mysql:host=localhost;dbname=monblog;charset=utf8', 'root', '');
$billets = $bdd->query('select BIL_ID as id, BIL_DATE as date,'
. ' BIL_TITRE as titre, BIL_CONTENU as contenu from T_BILLET'
. ' order by BIL_ID desc');
// Affichage
require 'vueAccueil.php';
Rappel : la fonction PHP require fonctionne de manire similaire include : elle inclut et excute le fichier spcifi.
En cas d'chec, include ne produit qu'un avertissement alors que require stoppe le script.
La balise de fin de code PHP ?> est volontairement omise la fin du fichier index.php. C'est
une bonne pratique pour les fichiers qui ne contiennent que du PHP. Elle permet d'viter des
problmes lors d'inclusions de fichiers.
Nous avons amlior l'architecture de notre page, mais nous pourrions gagner en modularit en isolant le code
d'accs aux donnes dans un fichier PHP ddi. Appelons ce fichier Modele.php.
Modele.php
<?php
-8-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Modele.php
return $billets;
}
Dans ce fichier, nous avons dplac la rcupration des billets du blog l'intrieur d'une fonction nomme getBillets.
Le code d'affichage (fichier vueAccueil.php) ne change pas. Le lien entre accs aux donnes et prsentation est
effectu par le fichier principal index.php. Ce fichier est maintenant trs simple.
index.php
<?php
require 'Modele.php';
$billets = getBillets();
require 'vueAccueil.php';
Outre la feuille de style CSS, notre page Web est maintenant constitue de trois fichiers :
Cette nouvelle structure est plus complexe, mais les responsabilits de chaque partie sont maintenant claires. En
faisant ce travail de refactoring, nous avons rendu notre exemple conforme un modle d'architecture trs employ
sur le Web : le modle MVC.
II-B-1 - Prsentation
Le modle MVC dcrit une manire d'architecturer une application informatique en la dcomposant en trois sous-
parties :
la partie Modle ;
la partie Vue ;
la partie Contrleur.
Ce modle de conception ( design pattern ) a t imagin la fin des annes 1970 pour le langage Smalltalk
afin de bien sparer le code de l'interface graphique de la logique applicative. Il est utilis dans de trs nombreux
langages : bibliothques Swing et Model 2 (JSP) de Java, frameworks PHP, ASP.NET MVC, etc.
La partie Modle d'une architecture MVC encapsule la logique mtier ( business logic ) ainsi que l'accs aux
donnes. Il peut s'agir d'un ensemble de fonctions (Modle procdural) ou de classes (Modle orient objet).
La partie Vue s'occupe des interactions avec l'utilisateur : prsentation, saisie et validation des donnes.
La partie Contrleur gre la dynamique de l'application. Elle fait le lien entre l'utilisateur et le reste de l'application.
-9-
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Le diagramme ci-dessous rsume les relations entre les composants d'une architecture MVC.
1 La demande de l'utilisateur (exemple : requte HTTP) est reue et interprte par le Contrleur.
2 Celui-ci utilise les services du Modle afin de prparer les donnes afficher.
3 Ensuite, le Contrleur fournit ces donnes la Vue, qui les prsente l'utilisateur (par exemple sous la
forme d'une page HTML).
Une application construite sur le principe du MVC se compose toujours de trois parties distinctes. Cependant, il
est frquent que chaque partie soit elle-mme dcompose en plusieurs lments. On peut ainsi trouver plusieurs
modles, plusieurs vues ou plusieurs contrleurs l'intrieur d'une application MVC.
Le modle MVC offre une sparation claire des responsabilits au sein d'une application, en conformit avec les
principes de conception dj tudis : responsabilit unique, couplage faible et cohsion forte. Le prix payer est
une augmentation de la complexit de l'architecture.
Dans le cas d'une application Web, l'application du modle MVC permet aux pages HTML (qui constituent la partie
Vue) de contenir le moins possible de code serveur, tant donn que le scripting est regroup dans les deux autres
parties de l'application.
Attention ne pas employer le terme de couche propos du modle MVC. Un modle en couches se caractrise
par l'interdiction pour une couche non transversale de communiquer au-del des couches adjacentes. De plus, le
nombre de couches n'est pas impos : il est fonction de la complexit du contexte.
- 10 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Mme si notre architecture a dj t nettement amliore, il est possible d'aller encore plus loin.
Un site Web se rduit rarement une seule page. Il serait donc souhaitable de dfinir un seul endroit les lments
communs des pages HTML affiches l'utilisateur (les vues).
Une premire solution consiste inclure les lments communs avec des fonctions PHP include. Il existe une autre
technique, plus souple, que nous allons mettre en uvre : l'utilisation d'un modle de page (gabarit), appel template
en anglais. Ce modle contiendra tous les lments communs et permettra d'ajouter les lments spcifiques
chaque vue. On peut crire ce template de la manire suivante (fichier gabarit.php).
gabarit.php
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="style.css" />
<title><?= $titre ?></title> <!-- lment spcifique -->
</head>
<body>
<div id="global">
<header>
<a href="index.php"><h1 id="titreBlog">Mon Blog</h1></a>
<p>Je vous souhaite la bienvenue sur ce modeste blog.</p>
</header>
<div id="contenu">
<?= $contenu ?> <!-- lment spcifique -->
</div>
<footer id="piedBlog">
Blog ralis avec PHP, HTML5 et CSS.
</footer>
</div> <!-- #global -->
</body>
</html>
- 11 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Au moment de l'affichage d'une vue HTML, il suffit de dfinir les valeurs des lments spcifiques, puis de dclencher
le rendu de notre gabarit. Pour cela, on utilise des fonctions PHP qui manipulent le flux de sortie de la page. Voici
notre page vueAccueil.php rcrite :
vueAccueil.php
<?php $titre = 'Mon Blog'; ?>
L'affichage utilisateur est strictement le mme qu'avant l'utilisation d'un gabarit. Cependant, nous disposons
maintenant d'une solution souple pour crer plusieurs vues tout en centralisant la dfinition de leurs lments
communs.
On peut amliorer l'architecture de la partie Modle en isolant le code qui tablit la connexion la base de donnes
sous la forme d'une fonction getBdd ajoute dans le fichier Modele.php. Cela vitera de dupliquer le code de
connexion lorsque nous ajouterons d'autres fonctions au Modle.
Modele.php
<?php
- 12 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Modele.php
}
Par souci de simplification, nous avions mis de ct la problmatique de la gestion des erreurs. Il est temps de s'y
intresser. Pour commencer, il faut dcider quelle partie de l'application aura la responsabilit de traiter les erreurs
qui pourraient apparatre lors de l'excution. Ce pourrait tre le Modle, mais il ne pourra pas les grer correctement
lui seul ni informer l'utilisateur. La Vue, ddie la prsentation, n'a pas s'occuper de ce genre de problmatique.
Le meilleur choix est donc d'implmenter la gestion des erreurs au niveau du Contrleur. Grer la dynamique de
l'application, y compris dans les cas dgrads, fait partie de ses responsabilits.
Nous allons tout d'abord modifier la connexion la base de donnes afin que les ventuelles erreurs soient signales
sous la forme d'exceptions.
Modele.php
...
$bdd = new PDO('mysql:host=localhost;dbname=monblog;charset=utf8',
'root', '', array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
...
On peut ensuite ajouter notre page une gestion minimaliste des erreurs de la manire suivante :
index.php
<?php
require 'Modele.php';
try {
$billets = getBillets();
require 'vueAccueil.php';
}
catch (Exception $e) {
echo '<html><body>Erreur ! ' . $e->getMessage() . '</body></html>';
}
Le premier require inclut uniquement la dfinition d'une fonction et est plac en dehors du bloc try. Le reste du
code est plac l'intrieur de ce bloc. Si une exception est leve lors de son excution, une page HTML minimale
contenant le message d'erreur est affiche.
On peut souhaiter conserver l'affichage du gabarit des vues mme en cas d'erreur. Il suffit de dfinir une vue
vueErreur.php ddie leur affichage.
vueErreur.php
<?php $titre = 'Mon Blog'; ?>
On modifie ensuite le contrleur pour dclencher le rendu de cette vue en cas d'erreur.
index.php
<?php
require 'Modele.php';
try {
$billets = getBillets();
- 13 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
index.php
require 'vueAccueil.php';
}
catch (Exception $e) {
$msgErreur = $e->getMessage();
require 'vueErreur.php';
}
Nous avons accompli sur notre page d'exemple un important travail de refactoring qui a modifi son architecture en
profondeur. Notre page respecte prsent un modle MVC simple.
Afin de rendre notre contexte d'exemple plus raliste, nous allons ajouter un nouveau besoin : le clic sur le titre d'un
billet du blog doit afficher sur une nouvelle page le contenu et les commentaires associs ce billet.
Commenons par ajouter dans notre modle (fichier Modele.php) les fonctions d'accs aux donnes dont nous
avons besoin.
Modele.php
...
// Renvoie les informations sur un billet
function getBillet($idBillet) {
$bdd = getBdd();
$billet = $bdd->prepare('select BIL_ID as id, BIL_DATE as date,'
. ' BIL_TITRE as titre, BIL_CONTENU as contenu from T_BILLET'
. ' where BIL_ID=?');
$billet->execute(array($idBillet));
if ($billet->rowCount() == 1)
return $billet->fetch(); // Accs la premire ligne de rsultat
else
throw new Exception("Aucun billet ne correspond l'identifiant '$idBillet'");
}
- 14 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Modele.php
}
Nous crons ensuite une nouvelle vue vueBillet.php dont le rle est d'afficher les informations demandes.
vueBillet.php
<?php $titre = "Mon Blog - " . $billet['titre']; ?>
Bien entendu, cette vue dfinit les lments dynamiques $titre et $contenu, puis inclut le gabarit commun.
Enfin, on cre un nouveau fichier contrleur, billet.php, qui fait le lien entre modle et vue pour rpondre au nouveau
besoin. Elle a besoin de recevoir en paramtre l'identifiant du billet. Elle s'utilise donc sous la forme billet.php?
id=<id du billet>.
billet.php
<?php
require 'Modele.php';
try {
if (isset($_GET['id'])) {
// intval renvoie la valeur numrique du paramtre ou 0 en cas d'chec
$id = intval($_GET['id']);
if ($id != 0) {
$billet = getBillet($id);
$commentaires = getCommentaires($id);
require 'vueBillet.php';
}
else
throw new Exception("Identifiant de billet incorrect");
}
else
throw new Exception("Aucun identifiant de billet");
}
catch (Exception $e) {
$msgErreur = $e->getMessage();
require 'vueErreur.php';
}
Il faut galement modifier la vue vueAccueil.php afin d'ajouter un lien vers la page billet.php sur le titre du billet.
vueAccueil.php
...
<header>
<a href="<?= "billet.php?id=" . $billet['id'] ?>">
<h1 class="titreBillet"><?= $billet['titre'] ?></h1>
- 15 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
vueAccueil.php
</a>
<time><?= $billet['date'] ?></time>
</header>
...
Pour finir, on enrichit la feuille de style CSS afin de conserver une prsentation harmonieuse.
style.css
...
#titreReponses {
font-size : 100%;
}
- 16 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Pour remdier ces dfauts, il est frquent d'ajouter au site un contrleur frontal.
Le contrleur frontal constitue le point d'entre unique du site. Son rle est de centraliser la gestion des requtes
entrantes. Il utilise le service d'un autre contrleur pour raliser l'action demande et renvoyer son rsultat sous la
forme d'une vue.
Un choix frquent consiste transformer le fichier principal index.php en contrleur frontal. Nous allons mettre en
uvre cette solution.
Ce changement d'architecture implique un changement d'utilisation du site. Voici comment fonctionne actuellement
notre blog :
La mise en uvre d'un contrleur frontal implique que index.php recevra la fois les demandes d'affichage de la liste
des billets et les demandes d'affichage d'un billet prcis. Il faut donc lui fournir de quoi lui permettre d'identifier l'action
raliser. Une solution courante est d'ajouter l'URL un paramtre action. Dans notre exemple, voici comment ce
paramtre sera interprt :
- 17 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
si action n'est pas valoris, le contrleur dclenchera l'affichage de la liste des billets (action par dfaut).
Toutes les actions ralisables sont rassembles sous la forme de fonctions dans le fichier Controleur.php.
Controleur.php
<?php
require 'Modele.php';
L'action raliser est dtermine par le fichier index.php de notre blog, rcrit sous la forme d'un contrleur frontal.
index.php
<?php
require('Controleur.php');
try {
if (isset($_GET['action'])) {
if ($_GET['action'] == 'billet') {
if (isset($_GET['id'])) {
$idBillet = intval($_GET['id']);
if ($idBillet != 0)
billet($idBillet);
else
throw new Exception("Identifiant de billet non valide");
}
else
throw new Exception("Identifiant de billet non dfini");
}
else
throw new Exception("Action non valide");
}
else {
accueil(); // action par dfaut
}
}
catch (Exception $e) {
erreur($e->getMessage());
}
Remarque : l'ancien fichier contrleur billet.php est dsormais inutile et peut tre supprim.
Enfin, le lien vers un billet doit tre modifi afin de reflter la nouvelle architecture.
vueAccueil.php
...
<a href="<?= "index.php?action=billet&id=" . $billet['id'] ?>">
<h1 class="titreBillet"><?= $billet['titre'] ?></h1>
- 18 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
vueAccueil.php
</a>
...
La mise en uvre d'un contrleur frontal a permis de prciser les responsabilits et de clarifier la dynamique de la
partie Contrleur de notre site :
Autre bnfice : l'organisation interne du site est totalement masque l'utilisateur, puisque seul le fichier index.php
est visible dans les URL. Cette encapsulation facilite les rorganisations internes, comme celle que nous allons
entreprendre maintenant.
Par souci de simplicit, nous avons jusqu' prsent stock tous nos fichiers source dans le mme rpertoire.
mesure que le site gagne en complexit, cette organisation montre ses limites. Il est maintenant difficile de deviner
le rle de certains fichiers sans les ouvrir pour examiner leur code.
Nous allons donc restructurer notre site. La solution la plus vidente consiste crer des sous-rpertoires en suivant
le dcoupage MVC :
On peut galement prvoir un rpertoire Contenu pour les contenus statiques (fichier CSS, images, etc.) et un
rpertoire BD pour le script de cration de la base de donnes. On aboutit l'organisation suivante :
Il est videmment ncessaire de mettre jour les inclusions et les liens pour prendre en compte la nouvelle
organisation des fichiers source. On remarque au passage que les mises jour sont localises et internes : grce
au contrleur frontal, les URL permettant d'utiliser notre site ne changent pas.
- 19 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Notre blog d'exemple est maintenant structur selon les principes du modle MVC, avec une sparation nette
des responsabilits entre composants qui se reflte dans l'organisation des sources. Notre solution est avant tout
procdurale : les actions du contrleur et les services du modle sont implments sous la forme de fonctions.
L'amlioration de l'architecture passe maintenant par la mise en uvre des concepts de la programmation oriente
objet, que PHP supporte pleinement depuis plusieurs annes.
Nous allons tudier le modle objet de PHP, et notamment ses spcificits par rapport d'autres langages comme
Java ou C#, travers l'exemple classique des comptes bancaires.
CompteBancaire.php
<?php
class CompteBancaire
{
private $devise;
private $solde;
private $titulaire;
- 20 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
CompteEpargne.php
<?php
require_once 'CompteBancaire.php';
poo.php
<?php
require 'CompteBancaire.php';
require 'CompteEpargne.php';
- 21 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
L'observation des exemples prcdents nous permet de retrouver certains concepts bien connus de la POO, repris
par PHP :
Mme s'il est similaire ceux de C#, Java ou C++, le modle objet de PHP possde certaines particularits :
PHP tant un langage typage dynamique, on ne prcise pas les types des attributs et des mthodes, mais
seulement leur niveau d'accessibilit ;
le mot-cl function permet de dclarer une mthode, quelle que soit sa valeur de retour ;
le mot-cl parent permet d'accder au parent de l'objet courant. Il joue en PHP le mme rle que base en C#
et super en Java ;
le constructeur d'une classe s'crit __construct ;
la mthode __toString dtermine comment l'objet est affich en tant que chane de caractres ;
on peut redfinir (override) une mthode, comme ici __toString, sans mot-cl particulier ;
le mot-cl $this est obligatoire pour accder aux membres de l'objet courant. Son utilisation est optionnelle
en C# et en Java, et souvent limite la leve des ambiguts entre attributs et paramtres ;
il est possible de dfinir une valeur par dfaut pour les paramtres d'une mthode. Elle est utilise lorsque
l'argument (paramtre effectif) n'est pas prcis au moment de l'appel.
Remarques :
Les mthodes __construct et __toString font partie de ce qu'on appelle les mthodes magiques.
L'instruction require_once est similaire require mais n'inclut le fichier demand qu'une seule fois. Elle est
utile pour viter, comme ici, les dfinitions multiples de classes.
Munis de cette connaissance minimale du modle objet de PHP, nous pouvons prsent amliorer l'architecture de
notre site d'exemple en tirant parti des possibilits de la POO.
Pour mmoire, voici la dfinition actuelle de notre partie Modle puis de notre partie Contrleur.
Modele.php
<?php
- 22 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Modele.php
function getBillet($idBillet) {
$bdd = getBdd();
$billet = $bdd->prepare('select BIL_ID as id, BIL_DATE as date,'
. ' BIL_TITRE as titre, BIL_CONTENU as contenu from T_BILLET'
. ' where BIL_ID=?');
$billet->execute(array($idBillet));
if ($billet->rowCount() == 1)
return $billet->fetch(); // Accs la premire ligne de rsultat
else
throw new Exception("Aucun billet ne correspond l'identifiant '$idBillet'");
}
On rappelle que le rle de la partie Modle est de rassembler la logique mtier et l'accs aux donnes.
Controleur.php
<?php
require 'Modele/Modele.php';
Dans le cadre d'un passage la POO, il serait envisageable de crer des classes mtier modlisant les entits du
domaine, en l'occurrence Billet et Commentaire.
- 23 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Plus modestement, nous allons nous contenter de dfinir les services d'accs aux donnes en tant que mthodes et
non comme simples fonctions. Voici une premire version de la classe Modele.
Modele.php
<?php
class Modele {
Par rapport notre ancien modle procdural, la seule relle avance offerte par cette classe est l'encapsulation (mot-
cl private) de la mthode de connexion la base. De plus, elle regroupe des services lis des entits distinctes
(billets et commentaires), ce qui est contraire au principe de cohsion forte, qui recommande de regrouper des
lments (par exemple des mthodes) en fonction de leur problmatique.
- 24 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Une meilleure solution consiste crer un modle par entit du domaine, tout en regroupant les services communs
dans une superclasse commune. On peut crire la classe Billet, en charge de l'accs aux donnes des billets,
comme ceci.
Billet
<?php
require_once 'Modele/Modele.php';
La classe Modele est dsormais abstraite (mot-cl abstract) et fournit ses classes drives un service d'excution
d'une requte SQL :
Modele.php
<?php
- 25 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
On remarque au passage que la technologie d'accs la base est totalement masque aux modles concrets, et
que Modele utilise la technique du chargement tardif ( lazy loading ) pour retarder l'instanciation de l'objet $bdd
sa premire utilisation.
On peut crire une classe Commentaire sur le mme modle que la classe Billet.
Commentaire.php
<?php
require_once 'Modele/Modele.php';
}
}
prsent, l'architecture de la partie Modele tire parti des avantages de la POO (encapsulation, hritage). Cette
architecture facilite les volutions : si le contexte mtier s'enrichit (exemple : gestion des auteurs de billets), il suffit de
crer une nouvelle classe modle drive de Modele (ici : Auteur) qui s'appuiera sur les services communs fournis
par sa superclasse.
Pour l'instant, nos vues sont des fichiers HTML/PHP qui exploitent des variables PHP contenant les donnes
dynamiques. Elles utilisent un gabarit commun regroupant les lments d'affichage communs. Voici par exemple la
vue d'affichage d'un billet et de ses commentaires.
vueBillet.php
<?php $titre = "Mon Blog - " . $billet['titre']; ?>
Le gabarit centralise les lments d'affichage communs et utilise les variables $titre et $contenu pour intgrer les
lments spcifiques.
gabarit.php
<!doctype html>
- 26 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
gabarit.php
<html lang="fr">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="Contenu/style.css" />
<title><?= $titre ?></title>
</head>
<body>
<div id="global">
<header>
<a href="index.php"><h1 id="titreBlog">Mon Blog</h1></a>
<p>Je vous souhaite la bienvenue sur ce modeste blog.</p>
</header>
<div id="contenu">
<?= $contenu ?>
</div> <!-- #contenu -->
<footer id="piedBlog">
Blog ralis avec PHP, HTML5 et CSS.
</footer>
</div> <!-- #global -->
</body>
</html>
Nous allons crer une classe Vue dont le rle sera de grer la gnration des vues.
Vue.php
class Vue {
- 27 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Vue.php
else {
throw new Exception("Fichier '$fichier' introuvable");
}
}
}
Le constructeur de Vue prend en paramtre une action, qui dtermine le fichier vue utilis. Sa mthode generer()
gnre d'abord la partie spcifique de la vue afin de dfinir son titre (attribut $titre) et son contenu (variable locale
$contenu). Ensuite, le gabarit est gnr en y incluant les lments spcifiques de la vue. Sa mthode interne
genererFichier() encapsule l'utilisation de require et permet en outre de vrifier l'existence du fichier vue afficher.
Elle utilise la fonction extract pour que la vue puisse accder aux variables PHP requises, rassembles dans le
tableau associatif $donnees.
Il n'est pas ncessaire de modifier le fichier gabarit. Par contre, les fichiers de chaque vue doivent tre modifis pour
dfinir $this->titre et supprimer les appels aux fonctions PHP de temporisation. Voici par exemple la nouvelle vue
d'accueil.
vueAccueil.php
<?php $this->titre = "Mon Blog"; ?>
L'affichage d'une vue se fera dsormais en instanciant un objet de la classe Vue, puis en appelant sa mthode
generer().
Notre partie Contrleur actuelle se compose d'une srie d'actions crites sous la forme de fonctions et du contrleur
frontal index.php.
Controleur.php
<?php
require 'Modele/Modele.php';
- 28 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Controleur.php
}
index.php
<?php
require 'Controleur/Controleur.php';
try {
if (isset($_GET['action'])) {
if ($_GET['action'] == 'billet') {
if (isset($_GET['id'])) {
$idBillet = intval($_GET['id']);
if ($idBillet != 0) {
billet($idBillet);
}
else
throw new Exception("Identifiant de billet non valide");
}
else
throw new Exception("Identifiant de billet non dfini");
}
else
throw new Exception("Action non valide");
}
else { // aucune action dfinie : affichage de l'accueil
accueil();
}
}
catch (Exception $e) {
erreur($e->getMessage());
}
Toute volution du site Web va faire augmenter le nombre d'actions possibles, jusqu' rendre les fichiers
Controleur.php et index.php difficiles lire et maintenir.
Une solution plus modulaire consiste rpartir les actions dans plusieurs classes contrleur, en fonction du contexte
associ aux actions. Ici, nous pourrions crer une classe ControleurAccueil pour grer l'accueil et une classe
ControleurBillet pour grer l'affichage d'un billet.
Bien entendu, les nouveaux contrleurs utilisent les services des classes des parties Modle et Vue dfinies
prcdemment.
ControleurAccueil.php
<?php
require_once 'Modele/Billet.php';
require_once 'Vue/Vue.php';
class ControleurAccueil {
private $billet;
- 29 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
ControleurBillet.php
<?php
require_once 'Modele/Billet.php';
require_once 'Modele/Commentaire.php';
require_once 'Vue/Vue.php';
class ControleurBillet {
private $billet;
private $commentaire;
Chaque classe contrleur instancie les classes modle requises, puis utilise leurs mthodes pour rcuprer les
donnes ncessaires aux vues. La mthode generer de la classe Vue dfinie plus haut est utilise en lui passant en
paramtre un tableau associatif contenant l'ensemble des donnes ncessaires la gnration de la vue. Chaque
lment de ce tableau est constitu d'une cl (entre apostrophes) et de la valeur associe cette cl.
Quant au contrleur frontal, on peut le modliser l'aide d'une classe Routeur dont la mthode principale analyse
la requte entrante pour dterminer l'action entreprendre. On parle souvent de routage de la requte.
Routeur.php
require_once 'Controleur/ControleurAccueil.php';
require_once 'Controleur/ControleurBillet.php';
require_once 'Vue/Vue.php';
class Routeur {
private $ctrlAccueil;
private $ctrlBillet;
- 30 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Routeur.php
else { // aucune action dfinie : affichage de l'accueil
$this->ctrlAccueil->accueil();
}
}
catch (Exception $e) {
$this->erreur($e->getMessage());
}
}
Le fichier principal index.php est maintenant simplifi l'extrme. Il se contente d'instancier le routeur puis de lui
faire router la requte.
index.php
<?php
require 'Controleur/Routeur.php';
La structure actuelle du site est prsente ci-dessous. Elle est videmment beaucoup plus complexe qu'au dpart.
Cette complexit est le prix payer pour disposer de bases robustes qui faciliteront la maintenance et les volutions
futures.
- 31 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
On souhaite maintenant que l'affichage des dtails sur un billet permette d'ajouter un nouveau commentaire. Le
remplissage des champs Auteur et Commentaire est obligatoire. Le clic sur le bouton Commenter dclenche l'insertion
du commentaire dans la base de donnes et la ractualisation de la page Web.
- 32 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
On commence par ajouter la classe Commentaire une mthode permettant d'insrer un nouveau commentaire
dans la BD.
Commentaire.php
...
// Ajoute un commentaire dans la base
public function ajouterCommentaire($auteur, $contenu, $idBillet) {
$sql = 'insert into T_COMMENTAIRE(COM_DATE, COM_AUTEUR, COM_CONTENU, BIL_ID)'
. ' values(?, ?, ?, ?)';
- 33 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Commentaire.php
$date = date(DATE_W3C); // Rcupre la date courante
$this->executerRequete($sql, array($date, $auteur, $contenu, $idBillet));
}
...
On ajoute ensuite la vue d'un billet le formulaire HTML ncessaire pour saisir un commentaire.
vueBillet.php
...
<form method="post" action="index.php?action=commenter">
<input id="auteur" name="auteur" type="text" placeholder="Votre pseudo"
required /><br />
<textarea id="txtCommentaire" name="contenu" rows="4"
placeholder="Votre commentaire" required></textarea><br />
<input type="hidden" name="id" value="<?= $billet['id'] ?>" />
<input type="submit" value="Commenter" />
</form>
Au passage, on met jour la feuille de style afin de dfinir la taille par dfaut de la zone de texte du commentaire.
style.css
...
#txtCommentaire {
width: 50%;
}
ControleurBillet.php
...
// Ajoute un commentaire un billet
public function commenter($auteur, $contenu, $idBillet) {
// Sauvegarde du commentaire
$this->commentaire->ajouterCommentaire($auteur, $contenu, $idBillet);
// Actualisation de l'affichage du billet
$this->billet($idBillet);
}
...
Cette action consiste appeler un service du Modle, puis excuter l'action d'affichage du billet afin d'obtenir un
rsultat actualis.
Enfin, on met jour le routeur afin de router une requte d'ajout de commentaire vers la nouvelle action. Au passage,
on en profite pour simplifier la mthode de routage (qui tend devenir complexe) en faisant appel une mthode
prive de recherche d'un paramtre dans un tableau. Cette mthode permet de rechercher un paramtre dans $_GET
ou $_POST en fonction du besoin.
Routeur.php
...
// Recherche un paramtre dans un tableau
private function getParametre($tableau, $nom) {
if (isset($tableau[$nom])) {
return $tableau[$nom];
}
else
throw new Exception("Paramtre '$nom' absent");
}
...
- 34 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Routeur.php
...
if (isset($_GET['action'])) {
if ($_GET['action'] == 'billet') {
$idBillet = intval($this->getParametre($_GET, 'id'));
if ($idBillet != 0) {
$this->ctrlBillet->billet($idBillet);
}
else
throw new Exception("Identifiant de billet non valide");
}
else if ($_GET['action'] == 'commenter') {
$auteur = $this->getParametre($_POST, 'auteur');
$contenu = $this->getParametre($_POST, 'contenu');
$idBillet = $this->getParametre($_POST, 'id');
$this->ctrlBillet->commenter($auteur, $contenu, $idBillet);
}
else
throw new Exception("Action non valide");
}
else { // aucune action dfinie : affichage de l'accueil
$this->ctrlAccueil->accueil();
}
...
Nous avons parcouru beaucoup de chemin depuis le dbut de cet article. D'une simple page PHP, notre blog
d'exemple s'est transform en un site Web architectur selon les principes du modle MVC. Il dispose d'un contrleur
frontal, d'un routeur orient objet, ainsi que de classes abstraites fournissant des services communs. Pourquoi ne
pas aller au bout de la logique objet en isolant ces services communs au sein d'un framework dont les bases sont
dj construites ?
Un framework fournit un ensemble de services de base, gnralement sous la forme de classes en interaction.
condition de respecter l'architecture qu'il prconise (pratiquement toujours une dclinaison du modle MVC), un
framework PHP libre le dveloppeur de nombreuses tches techniques comme le routage des requtes, la scurit,
la gestion du cache, etc. Cela lui permet de se concentrer sur l'essentiel, c'est--dire ses tches mtier. Il existe
une grande quantit de frameworks PHP. Parmi les plus connus, citons Symfony, Zend Framework ou encore
CodeIgniter.
Notre petit framework n'atteindra videmment pas la richesse fonctionnelle et le niveau de qualit des exemples
prcdents. Son but est d'illustrer de l'intrieur et aussi simplement que possible les bases du fonctionnement
d'un framework PHP.
Nous allons profiter de la mise en place du framework pour remdier certains points faibles de l'architecture actuelle :
les paramtres d'accs la base de donnes (serveur, nom de la BD, identifiant de connexion, mot de passe)
ne sont pas configurables ;
- 35 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
chaque classe modle instancie un objet PDO d'accs la BD, ce qui est sous-optimal du point de vue des
performances ;
les URL actuelles, du type monsite.fr/index.php?action=yyy&id=zzz, sont moins lisibles que des URL du
type monsite.fr/action/id ;
le routage de la requte (choix de l'action excuter) est fait manuellement par le routeur ;
les paramtres des requtes ne sont pas filtrs en entre ;
les donnes insres dans les vues ne sont pas nettoyes, ce qui accrot le risque de failles XSS.
Ce paragraphe constitue la partie la plus complexe de l'article. Il fait appel des concepts
avancs du dveloppement Web et de la POO.
Toutefois, il n'est pas ncessaire de comprendre tout son dtail pour pouvoir utiliser le
framework ainsi construit.
Commenons la construction du framework par la partie Modle. Les classes Billet et Commentaire sont directement
lies notre blog d'exemple et ne peuvent pas tre rutilises dans un autre contexte. En revanche, la classe abstraite
Modele fournit des services totalement indpendants du schma relationnel. On peut envisager de l'intgrer notre
framework.
Avant cela, il nous reste un problme rsoudre. Comme nous l'avons dit plus haut, l'accs la base de donnes
dans la classe abstraite Modele n'est pas paramtrable : les valeurs de la base MonBlog sont en dur dans son
code source.
Modele.php
<?php
- 36 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Pour que cette classe soit totalement gnrique et donc intgrable un framework, il faudrait pouvoir dfinir les
paramtres de connexion la BD sans modifier son code source. Pour cela, nous allons crer un nouveau composant
dont le rle sera de grer la configuration du site. Ce composant prend la forme d'une classe appele logiquement
Configuration.
Configuration.php
<?php
class Configuration {
Cette classe encapsule un tableau associatif cls/valeurs (attribut $parametres) stockant les valeurs des paramtres
de configuration. Ce tableau est statique (un seul exemplaire par classe), ce qui permet de l'utiliser sans instancier
d'objet Configuration.
La classe dispose d'une mthode statique publique nomme get() qui permet de rechercher la valeur d'un paramtre
partir de son nom. Si le paramtre en question est trouv dans le tableau associatif, sa valeur est renvoye. Sinon,
une valeur par dfaut est renvoye. On rencontre au passage le mot-cl PHP self qui permet de faire rfrence
un membre statique.
Enfin, la mthode statique prive getParametres() effectue le chargement tardif du fichier contenant les paramtres
de configuration. Afin de faire cohabiter sur un mme serveur une configuration de dveloppement et une
configuration de production, deux fichiers sont recherchs dans le rpertoire Config du site : dev.ini (cherch en
premier) et prod.ini. La lecture du fichier de configuration utilise la fonction PHP parse_ini_file(). Celle-ci instancie
et renvoie un tableau associatif immdiatement attribu l'attribut $parametres.
Grce cette classe, on peut externaliser la configuration d'un site en dehors de son code source. Voici par exemple
le fichier de configuration correspondant notre blog d'exemple.
dev.ini
; Configuration pour le dveloppement
[BD]
dsn = 'mysql:host=localhost;dbname=monblog;charset=utf8'
- 37 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
dev.ini
login = root
mdp =
Un changement de paramtres de connexion, par exemple pour employer un autre utilisateur que root, ncessite
uniquement une mise jour de ce fichier de configuration.
De plus, nous pouvons rendre la classe abstraite Modele totalement gnrique et rutilisable.
Modele.php
<?php
require_once 'Configuration.php';
/**
* Classe abstraite Modle.
* Centralise les services d'accs une base de donnes.
* Utilise l'API PDO de PHP
*
* @version 1.0
* @author Baptiste Pesquet
*/
abstract class Modele {
/**
* Excute une requte SQL
*
* @param string $sql Requte SQL
* @param array $params Paramtres de la requte
* @return PDOStatement Rsultats de la requte
*/
protected function executerRequete($sql, $params = null) {
if ($params == null) {
$resultat = self::getBdd()->query($sql); // excution directe
}
else {
$resultat = self::getBdd()->prepare($sql); // requte prpare
$resultat->execute($params);
}
return $resultat;
}
/**
* Renvoie un objet de connexion la BDD en initialisant la connexion au besoin
*
* @return PDO Objet PDO de connexion la BDD
*/
private static function getBdd() {
if (self::$bdd === null) {
// Rcupration des paramtres de configuration BD
$dsn = Configuration::get("dsn");
$login = Configuration::get("login");
$mdp = Configuration::get("mdp");
// Cration de la connexion
self::$bdd = new PDO($dsn, $login, $mdp,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
}
return self::$bdd;
}
- 38 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Au passage, on transforme l'attribut $bdd en attribut de classe (mot-cl static) afin de ne crer qu'une seule instance
de la classe PDO partage par toutes les classes drives de Modele. Ainsi, l'opration de connexion la base de
donnes ne sera ralise qu'une seule fois.
On remarque que la syntaxe d'appel d'une mthode de classe (ici Configuration::get()) utilise la notation :: comme
en C++.
prsent, intressons-nous la partie Contrleur de notre exemple. Les actions dfinies (affichage des billets, d'un
billet, commentaire) sont spcifiques notre contexte. En revanche, le routage d'une requte (choix de l'action
excuter en fonction des paramtres de la requte) pourrait tre rendu gnrique et intgr au framework.
Pour atteindre cet objectif complexe, nous allons commencer par ajouter une classe Requete dont le rle est de
modliser une requte. Pour l'instant, le seul attribut de cette classe est un tableau rassemblant les paramtres de
la requte. Par la suite, on pourrait y ajouter d'autres informations sur la requte : en-ttes HTTP, session, etc.
Requete.php
<?php
class Requete {
// paramtres de la requte
private $parametres;
Au dbut du routage, un objet Requete sera instanci afin de stocker les paramtres de la requte reue.
Le routage d'une requte entrante consiste analyser cette requte afin d'en dduire le contrleur utiliser et l'action
(mthode du contrleur) appeler. Ce travail est ralis par la classe Routeur, dont voici la version actuelle.
Routeur.php
<?php
require_once 'Controleur/ControleurAccueil.php';
require_once 'Controleur/ControleurBillet.php';
require_once 'Vue/Vue.php';
class Routeur {
private $ctrlAccueil;
private $ctrlBillet;
- 39 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Routeur.php
public function __construct() {
$this->ctrlAccueil = new ControleurAccueil();
$this->ctrlBillet = new ControleurBillet();
}
Pour l'instant, le choix de l'action s'effectue par comparaison du paramtre action de la requte avec diffrentes
valeurs prdfinies ( billet et commenter ). Cette opration est manuelle et devient complexe avec
l'augmentation du nombre des actions possibles.
On peut prsent modifier en profondeur le code du routeur afin de rendre le routage automatique et donc gnrique.
Routeur.php
<?php
require_once 'Requete.php';
- 40 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Routeur.php
require_once 'Vue.php';
class Routeur {
$controleur = $this->creerControleur($requete);
$action = $this->creerAction($requete);
$controleur->executerAction($action);
}
catch (Exception $e) {
$this->gererErreur($e);
}
}
La mthode principale routerRequete() de cette classe instancie un objet Requete en fusionnant les donnes des
variables superglobales $_GET et $_POST, afin de pouvoir analyser toute requte issue soit d'une commande HTTP
GET, soit d'une commande HTTP POST.
Ensuite, cette mthode fait appel deux mthodes internes afin d'instancier le contrleur appropri et d'excuter
l'action correspondant la requte reue.
La mthode creerControleur() rcupre le paramtre controleur de la requte reue et le concatne pour construire
le nom du fichier contrleur (celui qui contient la classe associe) et renvoyer une instance de la classe associe.
- 41 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
En l'absence de ce paramtre, elle cherche instancier la classe ControleurAccueil qui correspond au contrleur
par dfaut.
Cela n'est possible qu'en imposant tous les contrleurs des contraintes de nommage strictes : chaque contrleur doit
rsider dans le sous-rpertoire Controleur/ sous la forme d'un fichier dfinissant une classe nomme ControleurXXX
(XXX correspondant la valeur du paramtre controleur dans la requte). Le fichier doit porter le mme nom que
la classe.
Les plus attentifs d'entre vous auront remarqu que notre nouveau routeur fait appel aux mthodes setRequete() et
executerAction() de l'objet contrleur instanci. Il serait maladroit de dupliquer la dfinition de cette mthode dans
tous nos contrleurs. Nous allons donc dfinir une classe abstraite Controleur regroupant les services communs
aux contrleurs.
Controleur.php
<?php
require_once 'Requete.php';
require_once 'Vue.php';
// Action raliser
private $action;
// Requte entrante
protected $requete;
- 42 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Cette classe a pour attributs l'action raliser et la requte. Sa mthode executerAction() met en uvre le concept
de rflexion : elle utilise les fonctions PHP method_exists et get_class afin de faire appel la mthode ayant pour
nom l'action raliser.
La mthode index() est abstraite. Cela signifie que tous nos contrleurs, qui hriteront de Controleur, devront
obligatoirement dfinir une mthode index() qui correspond l'action par dfaut (quand le paramtre action n'est
pas dfini dans la requte).
Enfin, la mthode genererVue() permet d'automatiser le lien entre contrleur et vue : les paramtres de cration
de la vue sont dduits du nom du contrleur et de l'action raliser. Au passage, le constructeur de la classe Vue
doit voluer.
Vue.php
...
public function __construct($action, $controleur = "") {
// Dtermination du nom du fichier vue partir de l'action et du constructeur
$fichier = "Vue/";
if ($controleur != "") {
$fichier = $fichier . $controleur . "/";
}
$this->fichier = $fichier . $action . ".php";
}
...
L'automatisation du routage nous a conduit dfinir pour notre site des URL de la forme monsite.fr/index.php?
controleur=xxx&action=yyy&id=zzz. Afin de faciliter leur lisibilit et leur rfrencement, il serait souhaitable de les
remplacer par des URL de la forme monsite.fr/controleur/action/id. Ce format d'URL est adopt par la plupart des
plates-formes PHP modernes (frameworks, CMS, etc.). Par exemple, l'URL pour accder l'action index sur le billet
3 sera monsite.fr/billet/index/3.
Cette amlioration peut tre ralise grce au mcanisme de rcriture d'URL ( URL rewriting ). Il consiste
configurer le serveur Web pour transformer la vole l'URL reue.
Le serveur Web Apache dispose d'un puissant module de rcriture d'URL nomm mod_rewrite. Pour le mettre en
uvre, il faut ajouter la racine de notre site un fichier de configuration nomm .htaccess.
.htaccess
# Rcrit une URL de type xxx/yyy/zzz en index.php?controleur=xxx&action=yyy&id=zzz
RewriteEngine on
RewriteRule ^([a-zA-Z]*)/?([a-zA-Z]*)?/?([a-zA-Z0-9]*)?/?$ index.php?controleur=$1&action=$2&id=
$3 [NC,L]
Cependant, ce nouveau format d'URL provoque des erreurs avec les liens relatifs de nos vues (inclusion de feuilles de
style, d'images, de fichiers JavaScript, etc.). En effet, le navigateur rsout ces liens partir du chemin relatif dfini par
la nouvelle URL et non plus depuis la racine du site. Pour rsoudre ce problme, il faut ajouter dans toutes nos vues
la balise HTML base. La solution naturelle est d'inclure cette balise dans notre gabarit commun toutes les vues.
- 43 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
gabarit.php
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<base href="<?= $racineWeb ?>" >
...
La valeur de l'lment base est donne par la variable PHP $racineWeb qui doit tre dfinie au moment de la
gnration d'une vue. Pour cela, on modifie la mthode associe dans la classe Vue.
Vue.php
...
public function generer($donnees) {
// Gnration de la partie spcifique de la vue
$contenu = $this->genererFichier($this->fichier, $donnees);
// On dfinit une variable locale accessible par la vue pour la racine Web
// Il s'agit du chemin vers le site sur le serveur Web
// Ncessaire pour les URI de type controleur/action/id
$racineWeb = Configuration::get("racineWeb", "/");
// Gnration du gabarit commun utilisant la partie spcifique
$vue = $this->genererFichier('Vue/gabarit.php',
array('titre' => $this->titre, 'contenu' => $contenu,
'racineWeb' => $racineWeb));
// Renvoi de la vue gnre au navigateur
echo $vue;
}
}
...
Grce au composant de configuration cr plus haut, la valeur de racine Web est rcupre depuis le fichier de
configuration du site. Dans ce fichier, elle doit correspondre au chemin relatif de dploiement sur le serveur Web. Par
exemple, pour un site dploy dans monsite.fr/MonBlog, la valeur de racineWeb doit tre la suivante :
dev.ini
; Configuration pour le dveloppement
[Installation]
racineWeb = /MonBlog/
...
Jusqu' prsent, nous n'avons que trs peu abord les problmatiques lies la scurit du site. Il s'agit d'un vaste
sujet aux ramifications nombreuses. En matire de dveloppement Web, la rgle de scurit essentielle est de ne
jamais faire confiance aux donnes reues. Le Web est un monde ouvert o il est facile de forger une requte
HTTP contenant des paramtres intentionnellement incorrects. Deux exemples frquents sont l'injection de code sur
la page Web finale (cross-site scripting ou XSS) et l'injection SQL (excution par le SGBD de requtes SQL non
prvues). Afin de se prmunir contre de telles attaques, il est indispensable de nettoyer ( sanitize ) les donnes
reues ou affiches par le site.
Concernant les injections SQL visant la base de donnes, la solution consiste utiliser des requtes paramtres
plutt que de construire la requte SQL par concatnation d'instructions et de paramtres. Dans ce cas, le moteur
du SGBD effectue un nettoyage automatique des paramtres. Notre partie Modle utilise dj des requtes
paramtres : nous n'avons donc pas de prcaution supplmentaire prendre ce sujet.
La mthode de lutte contre les injections de code sur la page Web finale consiste nettoyer ( chapper )
systmatiquement toute donne insre dans la page. Autrement dit, nous devons ajouter nos vues un mcanisme
de nettoyage des valeurs PHP insres. Une solution simple est d'ajouter la classe Vue une mthode de nettoyage.
- 44 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Vue.php
...
// Nettoie une valeur insre dans une page HTML
private function nettoyer($valeur) {
return htmlspecialchars($valeur, ENT_QUOTES, 'UTF-8', false);
}
...
Il existe plusieurs solutions pour nettoyer une valeur avant son insertion dans une page HTML. La fonction
htmlspecialchars utilise ici remplace les caractres spciaux comme < ou > par les entits HTML associes
(ici, < deviendra < et > deviendra > ). Ainsi, si la valeur est un script JavaScript ( <script></
script> ), son nettoyage empchera l'excution du script par le moteur JavaScript du navigateur affichant la page
HTML.
Bien entendu, toutes les vues doivent faire appel cette mthode pour chacune des donnes dynamiques insres
dans les pages HTML.
La dernire tape de la construction de notre framework consiste regrouper les lments qui le composent. Pour
cela, on cre un rpertoire Framework/ dans lequel on dplace les fichiers source des six classes qui le composent.
Profitons-en pour numrer les contraintes que le framework impose l'architecture du site qui l'utilise :
un rpertoire Config/ contient le ou les fichiers de configuration (dev.ini et prod.ini) lues par la classe
Configuration ;
un rpertoire Controleur/ contient tous les contrleurs ;
chaque classe contrleur (ainsi que le fichier PHP associ) commence par le terme Controleur (exemple :
ControleurAccueil).
chaque action ralisable correspond une mthode publique dans la classe contrleur associe ;
une mthode index() (action par dfaut) est dfinie dans chaque contrleur ;
un rpertoire Vue/ contient toutes les vues ;
chaque vue est dfinie dans un sous-rpertoire de Vue/ portant le mme nom que le contrleur associ la
vue (exemple : Vue/Accueil/index.php pour la vue associe l'action par dfaut du contrleur d'accueil) ;
les fichiers gabarit.php (gabarit commun toutes les vues) et erreur.php (affichage du message d'erreur)
sont stocks dans le rpertoire Vue/ ;
- 45 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
prsent que notre framework est dfini, nous pouvons refactoriser notre blog d'exemple pour l'utiliser. Pour
commencer, voici le fichier de configuration utilis.
dev.ini
; Configuration pour le dveloppement
[Installation]
racineWeb = /MonBlog/
[BD]
dsn = 'mysql:host=localhost;dbname=monblog;charset=utf8'
login = root
mdp =
Puisque seule une mthode prive de la classe Modele a volu au cours de la construction du framework, aucune
classe de la partie Modle ne doit tre modifie. La seule mise jour consiste actualiser les inclusions du fichier
PHP contenant la classe Modele.
Billet.php, Commentaire.php
<?php
require_once 'Framework/Modele.php';
...
ControleurAccueil.php
<?php
require_once 'Framework/Controleur.php';
require_once 'Modele/Billet.php';
private $billet;
La classe ControleurBillet utilise les services de la classe Requete pour accder aux paramtres de la requte. Elle
utilise galement la mthode executerAction() de sa superclasse afin d'actualiser l'affichage des dtails sur le billet.
ControleurBillet.php
<?php
require_once 'Framework/Controleur.php';
require_once 'Modele/Billet.php';
require_once 'Modele/Commentaire.php';
- 46 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
ControleurBillet.php
class ControleurBillet extends Controleur {
private $billet;
private $commentaire;
$billet = $this->billet->getBillet($idBillet);
$commentaires = $this->commentaire->getCommentaires($idBillet);
Enfin, on dplace les fichiers vueAccueil.php et vueBillet.php dans les sous-rpertoires Vue/Accueil et Vue/Billet
respectivement, puis on les renomme tous les deux index.php puisque ces vues sont associes l'action par dfaut
de chacun des deux contrleurs. Le fichier vueErreur.php est renomme erreur.php. Le contenu des vues n'est pas
modifi, l'exception notable des appels systmatiques la mthode nettoyer() pour chaque donne incluse dans
la vue. Voici par exemple un extrait de la vue d'affichage des dtails d'un billet.
Vue/Billet/index.php
<?php $this->titre = "Mon Blog - " . $this->nettoyer($billet['titre']); ?>
<article>
<header>
<h1 class="titreBillet"><?= $this->nettoyer($billet['titre']) ?></h1>
<time><?= $this->nettoyer($billet['date']) ?></time>
</header>
<p><?= $this->nettoyer($billet['contenu']) ?></p>
...
VI - Conclusion et perspectives
Nous arrivons au terme de notre chantier de refactoring. Notre blog d'exemple utilise un framework MVC orient
objet qui lui fournit plusieurs services essentiels : configuration, interactions avec la base de donnes, routage des
requtes, URL gnriques, scurisation des donnes.
- 47 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Le framework que nous avons bti est totalement gnrique et rutilisable dans un autre contexte : il suffit de rcuprer
ses fichiers source (le contenu de Framework/ ainsi que les fichiers .htaccess et index.php de la racine), puis de
respecter les contraintes qu'il impose l'architecture du site (voir plus haut).
VI-B - Complments
La gestion de l'authentification est un besoin frquent lorsqu'on dveloppe un site Web. Afin de soumettre tout ou
partie du site authentification, on peut dfinir une superclasse abstraite ControleurSecurise pour les contrleurs.
Cette superclasse est charge de vrifier si le visiteur est authentifi et redirige vers la page de login si ce n'est pas
le cas. Cette solution est dtaille dans ce cours et sur cette branche du dpt GitHub.
Un autre besoin classique est d'ajouter aux vues des lments spcifiques lorsqu'un utilisateur est connect
(exemple : un message de bienvenue comportant son nom). Pour construire une vue personnalise si
l'utilisateur est connect, on peux complter la solution prcdente en dfinissant une autre classe abstraite
ControleurPersonnalise qui ajoute automatiquement les donnes client au moment de la gnration de la vue.
- 48 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
Un autre projet d'exemple sur GitHub utilise cette solution. Voici par exemple un extrait de la vue partielle Vue/
_Commun/barreNavigation.php
La variable dynamique $client est ajoute automatiquement aux donnes de la vue par tout contrleur qui hrite de
ControleurPersonnalise lorsque l'utilisateur est connect.
Afin de limiter sa complexit, notre framework reste minimaliste et donc largement perfectible. Les choix effectus
au cours de sa cration sont discutables et il est possible d'arriver un rsultat similaire par d'autres voies. Voici
quelques suggestions d'amliorations qui seront autant d'exercices enrichissants :
- 49 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/
voluer vers une architecture MVC en PHP par Baptiste Pesquet
ajouter des mcanismes de validation des donnes entrantes (exemple : si j'attends un entier, je vrifie que je
reois bien un entier) ;
intgrer un mcanisme de journalisation des vnements et des erreurs dans des fichiers journaux (log files) ;
utiliser un moteur de templates comme Twig pour les vues ;
intgrer des composants existants qui ont fait leurs preuves, par exemple l'excellent HttpFoundation issu du
framework Symfony.
Pour obtenir une architecture professionnelle, la meilleure solution consiste intgrer un framework PHP existant.
Ce cours dtaille une solution base sur le framework Silex, petit frre de Symfony.
Ainsi se termine cet article qui vous aura, j'espre, apport une meilleure comprhension des possibilits d'application
en PHP du modle MVC.
VII - Remerciements
Nous tenons remercier Benjamin Delespierre et Frdric Guillot pour leurs conseils aviss, ainsi que
ClaudeLELOUP pour sa relecture attentive.
- 50 -
Le contenu de cet article est rdig par Baptiste Pesquet et est mis disposition selon les termes de la Licence Creative Commons Attribution 3.0 non transpos. Les logos Developpez.com,
en-tte, pied de page, css, et look & feel de l'article sont Copyright 2013 Developpez.com.
http://bpesquet.developpez.com/tutoriels/php/evoluer-architecture-mvc/