Méthodologie de développement MVC d'une application PHP


précédentsommairesuivant

III. Un contrôleur générique

III-A. Introduction

Dans la méthode précédente, il était entendu que nous avions à écrire le contrôleur appelé main.php. Avec un peu d'expérience, on réalise que ce contrôleur fait souvent les mêmes choses et il est alors tentant d'écrire un contrôleur générique utilisable dans la plupart des applications web. Le code de ce contrôleur pourrait être le suivant :

 
CacherSélectionnez

III-B. Le fichier de configuration de l'application

L'application est configurée dans un script portant obligatoirement le nom config.php. Les paramètres de l'application sont mis dans un dictionnaire appelé $dConfig utilisé aussi bien par le contrôleur, que les scripts d'actions, les modèles et vues élémentaires.

III-C. Les bibliothèques à inclure dans le contrôleur

Les bibliothèques à inclure dans le code du contrôleur sont placées dans le tableau $dConfig['includes']. Le contrôleur les inclut avec la séquence de code suivante :

 
CacherSélectionnez

III-D. La gestion des sessions

Le contrôleur générique gère automatiquement une session. Il sauvegarde et récupère le contenu d'une session via le dictionnaire $dSession. Ce dictionnaire peut contenir des objets qu'il faut sérialiser pour pouvoir les récupérer ensuite correctement. La clé associée à ce dictionnaire est 'session'. Aussi récupérer une session se fait avec le code suivant :

 
CacherSélectionnez

Si une action souhaite mémoriser des informations dans la session, elle ajoutera des clés et des valeurs dans le dictionnaire $dSession. Toutes les actions partageant la même session, il y a un risque de conflit de clés de session si l'application est développée indépendamment par plusieurs personnes. C'est une difficulté. Il faut développer un référentiel listant les clés de session, référentiel partagé par tous. Nous verrons que chaque action se termine par l'appel à la fonction finSession suivante :

 
CacherSélectionnez

Une action peut décider de ne pas poursuivre une session. Il lui suffit pour cela de ne pas passer de valeur au paramètre $dSession de la fonction finSession, auquel cas la session est supprimée (session_destroy). Si le dictionnaire $dSession existe, il est sauvegardé dans la session et celle-ci est ensuite enregistrée (session_write_close). L'action en cours peut donc mémoriser des éléments dans la session en ajoutant des éléments au dictionnaire $dSession. On notera que le contrôleur mémorise automatiquement les paramètres de la requête courante dans la session. Cela permettra de les récupérer si besoin est pour traiter la requête suivante.

III-E. L'exécution des actions

Le contrôleur attend des requêtes ayant un paramètre action=XX. Si ce paramètre n'existe pas dans la requête et que celle-ci est un GET, l'action prend la valeur 'get:init'. C'est le cas de la toute première requête faite au contrôleur et qui est de la forme http://machine:port/chemin/main.php.

 
CacherSélectionnez

Par configuration, à chaque action est associé un script chargé de traiter cette action. Par exemple :

 
CacherSélectionnez

Deux actions sont prédéfinies :

 enchainementinvalide  cas où l'action en cours ne peut suivre l'action précédente
 actioninvalide  cas où l'action demandée n'existe pas dans le dictionnaire des actions

Les actions propres à l'application sont notées sous la forme méthode:action où méthode est la méthode get ou post de la requête et action l'action demandée, ici : init, calculerimpot, retourformulaire, effacerformulaire. On remarquera que l'action est récupérée, quelque soit la méthode GET ou POST d'envoi des paramètres, par la $_GET['action'] :

 
CacherSélectionnez

En effet, même si un formulaire est posté, on peut toujours écrire :

 
CacherSélectionnez

Les éléments du formulaire seront postés (method='post'). Néanmoins l'url demandée sera main.php?action=calculerimpot. Les paramètres de cette URL seront récupérés dans le dictionnaire $_GET alors que les autres éléments du formulaire seront eux récupérés dans le dictionnaire $_POST.

Muni du dictionnaire des actions, le contrôleur exécute l'action demandée de la façon suivante :

 
Sélectionnez
// traitement de l'action
    $scriptAction=$dConfig['actions'][$sAction] ?
    $dConfig['actions'][$sAction]['url'] :
    $dConfig['actions']['actioninvalide']['url'];
    include $scriptAction;

Si l'action demandée n'est pas dans le dictionnaire des actions, c'est le script correspondant à une action invalide qui sera exécuté. Une fois le script de l'action chargé au sein du contrôleur, il s'exécute. On remarquera qu'il a accès aux variables du contrôleur ($dConfig, $dSession) ainsi qu'aux dictionnaires super-globaux de PHP ($_GET, $_POST, $_SERVER, $_ENV, $_SESSION). On trouvera dans le script, de la logique applicative et des appels à des classes métier. Dans tous les cas, l'action devra

  • Renseigner le dictionnaire $dSession si des éléments doivent être sauvegardés dans la session courante
  • Indiquer dans $dReponse['vuereponse'] le nom du modèle de réponse à afficher
  • Se terminer par l'appel à finSession($dConfig, $dReponse, $dSession). Si la session doit être détruite, l'action se terminera simplement par l'appel à finSession($dConfig, $dReponse).

Par souci de cohérence, l'action pourra mettre dans le dictionnaire $dReponse toutes les informations dont ont besoin les vues. Mais il n'y a pas d'obligation. Seule la valeur $dReponse['vuereponse'] est indispensable. On remarquera que tout script d'action se termine par l'appel à la fonction finSession qui elle-même se termine par une opération exit. On ne revient donc pas d'un script d'action.

III-F. L'enchaînement des actions

On peut voir une application web comme un automate à états finis. Les différents états de l'application sont associés aux vues présentées à l'utilisateur. Celui-ci par le biais d'un lien ou d'un bouton va passer à une autre vue. L'application web a changé d'état. Nous avons vu qu'une action était initiée par une requête du genre http://machine:port/chemin/main.php?action=XX. Cette URL doit provenir d'un lien contenu dans la vue présentée à l'utilisateur. On veut en effet éviter qu'un utilisateur tape directement l'URL http://machine:port/chemin/main.php?action=XX court-circuitant ainsi le cheminement que l'application a prévu pour lui. Ceci est vrai également si le client est un programme.

Un enchaînement sera correct si l'URL demandée est une URL qui peut être demandée à partir de la dernière vue présentée à l'utilisateur. La liste de celles-ci est simple à déterminer. Elle est constituée

  • Des URL contenues dans la vue soit sous forme de liens sois sous forme de cibles d'actions de type [submit]
  • Des URL qu'un utilisateur est autorisé à taper directement dans son navigateur lorsque la vue lui est présentée.

La liste des états de l'applications ne se confond pas nécessairement avec celle des vues. Considérons par exemple une vue élémentaire erreurs.php suivante :

 
CacherSélectionnez

Cette vue élémentaire s'intègrera dans une composition de vues élémentaires qui formera la réponse. Sur cette vue, il y a un lien qui peut être positionné dynamiquement. La vue erreurs.php peut alors être affichée avec n liens différents selon les circonstances. Cela donnera naissance à n états différents pour l'application. Dans l'état n° i, la vue erreurs.php sera affichée avec le lien lieni. Dans cet état, seule l'utilisation du lien lieni est acceptable.

La liste des états d'une application et celle des actions possibles dans chaque état seront consignées dans le dictionnaire $dConfig ['etats'] :

 
CacherSélectionnez

L'application ci-dessus a deux états nommés : e-formulaire et e-erreurs. On rajoute un état appelé sansetat qui correspond au démarrage initial de l'application alors qu'elle n'avait pas d'état. Dans un état E, la liste des actions autorisées se trouve dans le tableau $dConfig['etats'][E]['actionsautorisees']. On y précise la méthode (get/post) autorisée pour l'action et le nom de celleci. Dans l'exemple ci-dessus, il y a quatre actions possibles : get:init, post:alculerimpot, get:retourformulaire et post:effacerformulaire.

Muni du dictionnaire $dConfig['etats'], le contrôleur peut dire si l'action $sAction en cours est autorisée ou non dans l'état actuel de l'application. Celui est construit par chaque action et stocké dans la session dans $dSession['etat']. Le code du contrôleur pour vérifier si l'action courante est autorisée ou non est le suivant :

 
CacherSélectionnez

La logique est la suivante : une action $sAction est autorisée si elle se trouve dans la liste $dConfig['etats'][$etat]['actionsautorisees'] ou si cette liste est inexistante autorisant alors toute action. $etat est l'état de l'application à la fin du précédent cycle demande client/réponse serveur. Cet état a été stocké dans la session et est retrouvé là. Si on découvre que l'action demandée est illégale, on fait exécuter le script $dConfig['actions']['enchainementinvalide']['url']. Ce script se chargera de transmettre une réponse adéquate au client.

En phase de développement, on pourra ne pas remplir le dictionnaire $dConfig['etats']. Dans ce cas, tout état autorise toute action. On pourra mettre au point le dictionnaire lorsque l'application aura été totalement déboguée. Il protègera l'application d'actions non autorisées.

III-G. L'envoi de la réponse au client

Le script [$scriptAction] de traitement de l'action courante place dans $dSession['etat']['principal'], l'état dans lequel doit être placée l'application. Cet état est l'une des clés du dictionnaire des états $dConfig['etats']. Dans l'exemple suivant :

 
CacherSélectionnez

On a deux états appelés [e-formulaire] et [e-erreurs]. A un état correspond un générateur de réponse et un seul. Ce générateur doit générer la réponse/vue à envoyer au client. Dans l'exemple ci-dessus, si un script d'action [$scriptAction] indique que l'application doit être mise dans l'état [e-formulaire], alors le contrôleur demandera l'exécution du script [e-formulaire.php]. Ceci est réalisé par la séquence de code suivante dans le contrôleur :

 
CacherSélectionnez

Le générateur de vue [$scriptVue] va s'exécuter et préparer la vue à envoyer. Chaque générateur de vue se termine par un appel à la procédure [finSession] du contrôleur générique. Celle-ci a pour objectif :

  • D'envoyer à l'utilisateur la vue préparée par le générateur [$scriptVue]
  • D'enregistrer certaines informations dans la session
  • De terminer l'exécution du contrôleur (exit)

Nous avons dit qu'une réponse pouvait avoir différents modèles de page. Ceux-ci sont placés par configuration dans ['vuesReponse']. Dans une application à deux modèles, on pourrait ainsi avoir :

 
CacherSélectionnez

Le générateur de vue précise dans $dReponse['vuereponse'] le modèle de la réponse désirée. Par exemple :

 
CacherSélectionnez

La réponse est envoyée au client par le contrôleur générique avec l'instruction :

 
CacherSélectionnez

Dans notre exemple, cela revient à écrire :

 
CacherSélectionnez

Le script [m-modele1.php] s'exécute. C'est une page PHP de présentation, sans logique de programmation mais avec des éléments dynamiques. Une fois cette page envoyée au client, le contrôleur s'arrête (exit). Le cycle demande-réponse du client-serveur est terminé.

III-H. Débogage

Le contrôleur propose deux fonction de débogage :

  • La fonction trace permet d'afficher un message dans le flux html
  • La fonction dump permet d'afficher le contenu d'un dictionnaire dans ce même flux

Tout script d'action pourra utiliser ces deux fonctions. En effet, le code du script d'action étant inclus (include) dans le code du contrôleur, les fonctions trace et dump seront visibles des scripts.

III-I. Conclusion

Le contrôleur générique vise à permettre au développeur de se concentrer sur les actions et les vues de son application. Il assure pour lui :

  • La gestion de la session (restauration, sauvegarde)
  • La vérification de la validité des actions demandées
  • L'exécution du script associé à l'action
  • L'envoi au client de la réponse adaptée à l'état résultat de l'exécution de l'action

précédentsommairesuivant

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2004 Serge Tahé. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.