Pour satisfaire votre curiosité, voici le code de la méthode execute dansFrontal.php ce fichier se trouve dans lib... Conformément à nos conventions, un contrơleur nommé control est impl
Trang 1248 Chapitre 6 Architecture du site : le pattern MVC
sont « normalisées » pour annuler l’échappement qui a éventuellement été pratiqué suite au paramétrage à On de magic_quotes_gpc
On peut ensuite développer tout le reste du site en considérant que magic_quotes_gpc vaut Off Il serait bien sûr plus facile de pouvoir changer la configuration au moment de l’exécution mais ce n’est pas possible pour cette directive Il est probable qu’elle sera supprimée en PHP 6
Notez enfin qu’on utilise la fonction init_set() pour fixer le paramètre display_errors Sa valeur est déterminée par la constante DISPLAY_ERRORS, définie dans le fichier Config.php, qu’il faut absolument placer à Off sur un site en production
6.2.2 Le contrôleur frontal
Le contrôleur frontal est une instance de la classe Frontal dont le rôle est de
« router » la requête HTTP vers le contrôleur et l’action appropriés Comme d’ha-bitude avec l’approche orientée-objet, on peut se contenter d’utiliser une classe sans connaître son implantation, ou inspecter cette dernière pour se faire une idée de la manière dont les choses sont traitées Pour satisfaire votre curiosité, voici le code de
la méthode execute() dansFrontal.php (ce fichier se trouve dans lib).
f u n c t i o n e x e c u t e ( )
{
/ / D ’ a b o r d , on r é c u p è r e l e s noms du c o n t r ô l e u r e t d e l ’ a c t i o n
i f ( i s S e t ( $_GET [ ’ c o n t r o l e u r ’ ] ) )
$ c o n t r o l e u r = u c f i r s t ( $_GET [ ’ c o n t r o l e u r ’ ] ) " C t r l " ;
e l s e
$ c o n t r o l e u r = " I n d e x C t r l " ;
i f ( i s S e t ( $_GET [ ’ a c t i o n ’ ] ) )
$ a c t i o n = l c f i r s t ( $_GET [ ’ a c t i o n ’ ] ) ;
e l s e
$ a c t i o n = " i n d e x " ;
/ / M a i n t e n a n t c h a r g e o n s l a c l a s s e
$chemin = " c o n t r o l e u r s " DIRECTORY_SEPARATOR $ c o n t r o l e u r " php " ;
i f ( f i l e _ e x i s t s ( " a p p l i c a t i o n " DIRECTORY_SEPARATOR $chemin
) ) {
r e q u i r e _ o n c e ( $chemin ) ;
} e l s e {
t h r o w new E x c e p t i o n ( " Le c o n t r ô l e u r <b> $ c o n t r o l e u r < / b> n ’
e x i s t e p a s " ) ; }
/ / On i n s t a n c i e un o b j e t
e v a l ( " \ $ c t r l = new $ c o n t r o l e u r ( ) ; " ) ;
/ / I l f a u t v é r i f i e r q u e l ’ a c t i o n e x i s t e
i f ( ! m e t h o d _ e x i s t s ( $ c t r l , $ a c t i o n ) ) {
Trang 2" ) ; }
/ / E t p o u r f i n i r i l n ’ y a p l u s qu ’ à e x é c u t e r l ’ a c t i o n
c a l l _ u s e r _ f u n c ( a r r a y ( $ c t r l , $ a c t i o n ) ) ;
}
Essentiellement, elle détermine le contrơleur et l’action en fonction des para-mètres reçus dans la requête HTTP Conformément à nos conventions, un contrơleur
nommé control est implanté par une classe nommée control Ctrl et se trouve dans le fichier control Ctrl.php du répertoire application/controleurs On vérifie
donc que ce fichier existe, faute de quoi on lève une exeption On instancie ensuite
ce contrơleur avec la fonction eval(), qui permet d’évaluer une expression PHP construite dynamiquement (ce qui est le cas ici puisqu’on ne sait pas à l’avance quel est le nom de la classe à instancier) Finalement on vérifie que l’action demandée est bien implantée par une méthode dans la classe instanciée, et si oui, on l’exécute
Ce fragment de code est un exemple de ce que l’on pourrait appeler « méta-programmation » en PHP : on crée par méta-programmation du code PHP que l’on exé-cute C’est une pratique assez courante en programmation avancée, car elle permet
de résoudre élégamment des problèmes assez difficiles à traiter dans des languages moins souples
En résumé, le contrơleur frontal charge la classe du contrơleur, l’instancie et exécute la méthode correspondant à l’action Voyons maintenant le contrơleur lui-même
6.2.3 Créer des contrơleurs et des actions
Créer un contrơleur est extrêmement simple : on ajoute un fichier nom Ctrl.php dans application/controleurs, ó nom est le nom du contrơleur Ce fichier contient une
classe qui hérite de Controleur Voici le code d’un contrơleur servant d’exemple
Exemple 6.2 webscope/application/controleurs/TestCtrl.php : Le contrơleur test
<? php
/ ∗ ∗
∗ @ c a t e g o r y w e b s c o p e
∗ @ c o p y r i g h t P h i l i p p e Rigaux , 2008
∗ @ l i c e n s e GPL
∗ @package t e s t
∗ /
r e q u i r e _ o n c e ( " C o n t r o l e u r php " ) ;
/ ∗ ∗
∗ C o n t r o l e u r de t e s t , m o n t r a n t comment i m p l a n t e r
∗ d e s a c t i o n s d a n s un c o n t r ơ l e u r
∗ /
Trang 3250 Chapitre 6 Architecture du site : le pattern MVC
c l a s s T e s t C t r l e x t e n d s C o n t r o l e u r
{
/ ∗ ∗
∗ A c t i o n p a r d é f a u t − a f f i c h a g e de l a l i s t e d e s r é g i o n s
∗ /
f u n c t i o n i n d e x ( )
{
/ / A f f i c h a g e d e l a l i s t e d e s r é g i o n s
$ r e s u l t a t = $ t h i s−>bd−>execRequete ( "SELECT ∗ FROM Region " ) ;
w h i l e ( $ r e g i o n = $ t h i s−>bd−>o b j e t S u i v a n t ( $ r e s u l t a t ) )
echo " <b> $ r e g i o n−>nom</ b><br / > " ;
}
}
? >
Le code est une classe qui sert simplement de « coquille » à une liste de méthodes publiques, sans paramètre, implantant les actions Ajouter une action revient donc à ajouter une méthode La seule action disponible ici est index, que l’on appelle avec l’URL :
http://serveur/webscope/index.php?ctrl=test&action=index
Ou bien, plus simplement
http://serveur/webscope/?ctrl=test
en tirant parti du fait qu’index est l’action par défaut, etindex.phple script par défaut
En étudiant cette action, on constate que l’objet-contrơleur dispose d’une pro-priété $this->bd, qui permet d’exécuter des requêtes D’ó vient cet objet ? De
la super-classe Controleur qui instancie automatiquement un objet de la classe BDMySQL dans son constructeur Tous les contrơleurs, sous-classes de Controleur, héritent de ce constructeur et, automatiquement, on dispose donc d’une connexion avec la base Voici le code du constructeur de Controleur
f u n c t i o n _ _ c o n s t r u c t ( )
{
/∗
∗ Le c o n t r ơ l e u r i n i t i a l i s e p l u s i e u r s o b j e t s u t i l i t a i r e s :
∗ − une i n s t a n c e de BD p o u r a c c é d e r à l a b a s e de d o n n é e s
∗ − une i n s t a n c e du m o t e u r de t e m p l a t e s p o u r g é r e r l a vue
∗ /
/ / I n i t i a l i s a t i o n d e l a s e s s i o n PHP
s e s s i o n _ s t a r t ( ) ;
/ / C o n n e x i o n à l a b a s e
$ t h i s−>bd = new BDMySQL (NOM, PASSE , BASE , SERVEUR) ;
Trang 4/ / I n s t a n c i a t i o n du m o t e u r d e t e m p l a t e s
$ t h i s−>vue = new Template ( " a p p l i c a t i o n "
DIRECTORY_SEPARATOR " v u e s " ) ;
/ / On c h a r g e s y s t é m a t i q u e m e n t l e " l a y o u t " du s i t e
$ t h i s−>vue−> s e t F i l e ( " page " , " l a y o u t t p l " ) ;
/ / e t i n i t i a l i s a t i o n du c o n t e n u e t du t i t r e
$ t h i s−>vue−>contenu =" " ;
$ t h i s−>vue−>t i t r e _ p a g e = " " ;
/ / R e c h e r c h e d e l a s e s s i o n
$ t h i s−> i n i t S e s s i o n ( s e s s i o n _ i d ( ) ) ;
/ / I n i t i a l i s a t i o n d e l a p a r t i e du c o n t e n u
/ / q u i m o n t r e s o i t un f o r m u l a i r e , d e c o n n e x i o n ,
/ / s o i t un l i e n d e d é c o n n e x i o n
$ t h i s−>s t a t u t C o n n e x i o n ( ) ;
}
On peut noter que le constructeur instancie également un moteur de templates pour gérer la vue, accessible dans $this->vue, ainsi que des informations relatives
à la session Nous y reviendrons
Au sein d’une action, on programme en PHP de manière tout à fait classique Il
ne s’agit pas vraiment de programmation orientée-objet au sens ó nous l’avons vu dans les chapitres précédents L’approche objet se borne ici à structurer le code, et à bénéficier du mécanisme d’héritage pour initialiser des composants utiles à toutes les actions
Retenez cette approche consistant à définir une super-classe pour définir un com-portement commun à un ensemble d’objets (ici les contrơleurs) Toutes les tâches répétitives d’intialisation de l’environnement, de configuration, de connexion à la base, etc., sont déjà faites une fois pour toutes Inversement, cela rend très facile l’ajout de nouvelles contraintes, communes à tous les objets, par enrichissement
de la super-classe Un simple exemple : que se passe-t-il si on écrit un contrơleur
en oubliant une méthode nommée index() ? Alors le choix par défaut effectué par le contrơleur frontal risque d’entraỵner une erreur puisque l’action par défaut, index, n’existe pas Solution : on définit cette action par défaut dans la super-classe
Controleur : elle existe alors, par héritage, dans tous les contrơleurs, et elle est
surchargée par toute méthode index() définie au niveau des sous-classes.
6.3 STRUCTURE D’UNE APPLICATION MVC : LA VUE
Le code de l’action index() du contrơleur test, présenté précédemment, affiche simplement la sortie avec la commande PHP echo C’est contraire au principe MVC
de séparer la production de la présentation du traitement des données L’inconvé-nient est de se retrouver à manipuler de très longues chaỵnes de caractères HTML dans le script, pratique qui mène extrêmement rapidement à un code illisible
Trang 5252 Chapitre 6 Architecture du site : le pattern MVC
Une solution très simple consisterait à organiser chaque page en trois parties, en-tête, contenu et pied de page, l’en-tête et le pied de page étant systématiquement produits par des fonctions PHP Entete() et PiedDePage() La figure 6.3 montre
le style d’interaction obtenu, chaque action (sur la gauche) produisant les différentes parties de la page
Item 1
Titre
Item n Item 2
MySQL contact PHP
Contenu de la page Code
PHP/MySQL entete()
PiedDePage()
Script PHP
Fonction Fonction
Figure 6.3 — Tout le code HTML est produit avec PHP.
Cette méthode est envisageable pour de petits sites pour lesquels la conception graphique est stable et peu compliquée Elle offre l’avantage de regrouper en un seul endroit (nos deux fonctions) les choix de présentation, et de rendre l’application indépendante de tout outil de production HTML
Pour des projets plus conséquents, il nous faut un composant
• gérant la vue,
• offrant une séparation claire entre les fragments HTML constituant la présen-tation des pages et le code PHP qui fournit le contenu
L’approche basée sur des templates, ou modèles de présentation, dans lesquels on
indique les emplacements ó le contenu produit dynamiquement doit être inséré, constitue une solution pratiquée depuis très longtemps Elle offre plusieurs avantages,
et quelques inconvénients Pour être concret, je vais donner des exemples de la gestion de la vue à base de templates, avant de revenir sur les principes généraux
de séparation du code HTML et du code PHP
6.3.1 Les templates
Le système utilisé pour nos exemples est un moteur de templates adapté de la bibliothèque PHPLIB et amélioré grâce aux possibilités de PHP 5 Ce moteur est
très représentatif des fonctionnalités des templates (dont il existe de très nombreux
représentants) et s’avère simple à utiliser Les méthodes publiques de la classe sont données dans le tableau 6.1