Dans un projet, une démarche de génie logiciel pousse à définir l'architecture d'une application dans le respect des design pattern. L'architecture MVC cherche à séparer trois choses :

  • la façon d'accéder aux données
  • l'interface homme/machine:  l'habillage, le design
  • les traitements liés au métier/domaine de l'application

Soit le Modèle, les Vues et les Contrôleurs. Les contrôleurs permettent de répondre aux actions de l'utilisateur. Chaque contrôle est associé à une vue : cette dernière permet de présenter l'information retournée à l'utilisateur. Les données sont issues du  modèle (la logique métier).



Les patterns ont une histoire et ne sont pas figés. Ainsi, le pattern MVC a évolué vers le MVC2. Dans l'architecture MVC 2, il n'existe plus qu'un seul et unique contrôleur réceptionnant toutes les requêtes clientes.
Le contrôleur unique devient le point d'entrée exclusif de l'application. Il devient alors très aisé de centraliser la gestion des accès, des droits, des statistiques ou de toute autre fonctionnalité transverse.

Concrètement, en quoi cela consiste t'il ? L'expression la plus simple d'une page affichant un listing de prix pourrait être la suivante.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//FR"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en_US" xml:lang=
"en_US">
  <head>
    <title>
      Exemple
    </title>
  </head>
  <body>
  <?php
    $db=mysql_connect($dbhost,$dbuser,$dbpass);
    mysql_select_db($dbname,$db);
    $query="SELECT product.name, product.price FROM product where product.type=42";
   $req=mysql_query($query)or die('Erreur SQL!<br>'.$sql.'<br>'.mysql_error());
   while ($row = mysql_fetch_array($req)) {
   echo "Nom :".$row[0]." Prix :".$row[1];
}
    mysql_close();  
  ?>  
  </body>
</html>
C'est simple, c'est court... mais tout est mélangé.
Découpons le code. (Les sources sont téléchargeables sur la page des ressources)
D'abord, en construisant un aiguillage à requête.

Point d'entré unique : index.php:
<?php
if  ($_GET['do']=="")
{                    
  require ("default.html");
}
else
{
  if($_GET['do']=="affichage")
  {
    require("action/class_example.php");
    new Example();
  }
}
?>
Ensuite, on isole le contrôleur (qui dans cet exemple ne fait pas grand chose)

Controleur : /action/class_example.php:

<?php
 require ("dao/dao_example_dao.php");
 
  class Example
 {
  public function example()
  {
    $exampleDao= new ExampleDao();
    $data = $exampleDao->get_products();
    require("web/affichage.phtml");
  
  }
}
?>

L'accès aux données est isolé dans une classe dao (Data access Object, autre design pattern)
Modèle : dao_example_dao.php

<?php
 require ("class_connect_bd.php");
 
 class ExampleDao
 {
   public  function get_products()
   {
    $sql = "SELECT product.name, product.price FROM product where product.type=42";
    $query = mysql_query($sql) or die('Erreur SQL !<br>'.mysql_error());
    $all =  mysql_fetch_all($query);
    return $all;
   }
 }
?>

Le lecteur averti notera que la fonction mysql_fetch_all() n'est pas une fonction native de php. Il convient de l'implémenter. Ici dans le class_connect_bd.php:


<?php
$db = mysql_connect('localhost', 'user', 'password');
mysql_select_db('test',$db);

 function mysql_fetch_all($query, $kind = 'assoc') {
    $result = array();
    $kind = $kind === 'assoc' ? $kind : 'row';
    eval('while(@$r = mysql_fetch_'.$kind.'($query)) array_push($result, $r);');
    return $result;
}
?>


Enfin, l'affichage:
Vue : /web/affichage.phtml:

<html xmlns="http://www.w3.org/1999/xhtml" lang="en_US" xml:lang="en_US">
  <head>
    <title>
      Exemple
    </title>
  </head>
  <body>
    <?
foreach ($data AS $row )
{
?>
   Nom :
<? echo $row["name"]; ?>
 Prix :
<? echo $row["price"]; ?> <br/>
<?
}
?>
  </body>
</html>

Attention: L'exemple se lance en passant en passant le paramètre do dans l'url :
index.php?do=affichage
Évidement sur un exemple court, l'explosion du nombre de lignes du code n'est pas à l'avantage du pattern. Toutefois, sur le développement d'une application, le rangement opéré sur le code est nécessaire. En effet, le MVC apporte un niveau d'industrialisation du code.

Cette architecture est particulièrement préconisée dans la mise en œuvre d'une application Web pour de nombreuses raisons.
Le point d'entré unique permet la mise en place de traitement centralisé. Typiquement, le contrôle d'accès. Plutôt que de copier coller (et oublier...) un test sur chaque page pour vérifier que l'utilisateur est identifié. On réalise ce test une fois et ce code est maintenu à un seul endroit.

Le code est également beaucoup plus facile à maintenir.
  • L'enchainement des écrans est défini par le point d'entré unique , une modification se fera à cet endroit (et pas en partant à la recherche des 90 liens perdus dans une montagne de code)
  • Si demain le produit n'est plus à chercher en base de données mais dans un service web, il est facile de ne modifier que le dao correspondant sans impacter la logique métier.
  • Et si le design évolue, seul les fichiers de la vue sont concernés.


Les bénéfices d'une bonne structuration d'un code sont nombreux. C'est pour cela  que  le MVC est devenu incontournable et qu'il est utilisé dans la quasi totalité des framework PHP.