mercredi 6 février 2013

Architecture MVC

Exercice 1

1) Dans le dossier /www/htdocs/sitezend, créez les dossiers nécessaires à une architecture MVC minimale


Exercice 2

1) Créez le nom de domaine local http://www.zendsite.com qui redirige vers votre serveur

2) Configurez un virtualhost pour que le nom de domaine précédemment créé pointe vers le dossier /www/htdocs/sitezend/html/


Exercice 3

1) Créez le bootstrap dans html/index.php

2) Créez le contrôleur et l'action index dans application/controllers/IndexController.php

3) Créez la vue de l'action index précédemment créée dans application/views/scripts/index/index.phtml


Exercice 4

1) Créez le contrôleur LoginController :


Exercice 5

1) Créez l'action mdpoublieAction() dans la méthode login qui affichera le formulaire permettant de récupérer un mot de passe oublié


Exercice 6

1) Récupérez les paramètres GET appelés dans http://www.zendsite.com/login/mdpoublie/prenom/paul/nom/danilo/


Exercice 7

1) Récupérez les paramètres POST appelés dans http://www.zendsite.com/login/mdpoublie/ via le formulaire html suivant :

<form method="POST" action="">
 
 
 
</form>

Exercice 8

1) Utilisez la méthode init() du contrôleur Login pour définir la variable view->TitrePage("Titre de ma page")

2) Affichez cette variable comme titre de la page.


Exercice 9

1) A l'aide de l'annexe 1, créez la vue layout.phtml dans le dossier /www/htdocs/sitezend/application/views/scripts/login/.

2) A l'aide de l'annexe 2, créez le gabarit /www/htdocs/sitezend/application/views/scripts/common/header.phtml.

3) A l'aide de l'annexe 3, créez le gabarit /www/htdocs/sitezend/application/views/scripts/common/footer.phtml

4) Appelez les gabarits header.phtml et footer.phtml dans la vue layout.phtml


Annexe 1


<?php echo $this->doctype("XHTML1_TRANSITIONAL"), PHP_EOL; ?>


<?php  echo $this->headMeta()
->setHttpEquiv('Content-Type', 'text/html; charset=utf-8')
->setHttpEquiv('Content-Style-Type', 'text/css')
->setHttpEquiv('lang', 'fr')
->setHttpEquiv('imagetoolbar', 'no')
->setName('language', 'fr');
echo $this->headTitle($this->TitrePage);
echo $this->headLink(array('rel' => 'favicon', 'type' => 'image/x-icon', 'href' => 'images/favicon.ico'));
echo $this->headStyle()->appendStyle('@import "css/styles.css";');
?>



Annexe 2

<div style="float: right; padding-top: 3px">
    <a href="<?php echo $this->baseUrl(); ?>">Accueil | <a href="">Nous contacter |
</div>
<div style="padding-top: 3px">
    <?php echo $this->escape($this->TitrePage); ?>
</div>

Annexe 3

<div style="margin-top:25px; text-align:center;">© 2013 ZendSite.com - tous droits réservé

De quoi parle t'on ?

Lors de vos premières applications PHP vous vous êtes sans doute senti obligé de créer un fichier .php par page et un certain nombre de dossiers pour regrouper divers fichiers

Au fil du temps votre application ne cesse de grossir et devient rapidement difficile à maintenir. Le plus douloureux arrive lorsque vous n'avez pas touché à votre application depuis plusieurs semaines et que vous devez retrouver comment vous l'aviez géré.

Cette méthode n'est pas pratique lorsque vous êtes seul à travailler dessus et devient totalement ingérable lorsque vous êtes plusieurs développeurs.

Globalement, nous pourrons accéder à une fonction directement en saisissant une URL. (une URL = une fonction à appeler)

Pour pallier à ce problème, l'architecture MVC (Model-View-Controller) a été créée et Zend Framework la gère comme un chef !

Dans une application Zend Framework, la partie MVC est située dans un dossier à part, nommé par défaut application.

Trois sous-dossiers controllers, views et models ont des noms explicites quant à leur contenu :

  • Dans le dossier controllers, le fichier IndexController.php contient le contrôleur principal de l’application, c’est-à dire celui qui est appelé par défaut.
  • Le fichier index.phtml, dans views/index, correspond à la vue du contrôleur principal. En fait, il s’agit de la vue de l’action index (nom du fichier) du contrôleur index (nom du dossier contenant).
  • Le fichier html/index.php est ce que l’on appelle un bootstrap ou « fichier d’amorçage ». C’est vers ce fichier que toutes les requêtes HTTP sont redirigées, mis à part celles des fichiers statiques (images, CSS, JavaScript...).

La requête HTTP passe d’abord par le contrôleur frontal qui est instancié dans le bootstrap (html/index.php). Ce contrôleur frontal va déterminer quel contrôleur et quelle action doivent être appelés. C’est ainsi, par exemple, que le contrôleur réservations est instancié et que l’action exporter est appelée.

Techniquement, un contrôleur est une classe, et l’action une méthode de cette dernière.


Correction de l'exercice 1

On créé les dossiers nécessaires au fonctionnement de notre architecture MVC

mkdir /www/htdocs/sitezend/

mkdir /www/htdocs/sitezend/application
mkdir /www/htdocs/sitezend/application/controllers
mkdir /www/htdocs/sitezend/application/models

mkdir /www/htdocs/sitezend/application/views
mkdir /www/htdocs/sitezend/application/views/scripts
mkdir /www/htdocs/sitezend/application/views/scripts/index

mkdir /www/htdocs/sitezend/html

Correction de l'exercice 2

On va rediriger le nom de domaine zendsite.com vers notre serveur, bien entendu vous ne deviendrez propriétaire de ce nom de domaine, seul votre ordinateur redirigera vers l'IP de votre serveur.

Si votre navigateur web se trouve sous Windows, vous devez ouvrir le fichier hosts qui se trouve dans C:\Windows\System32\drivers\etc\host avec votre éditeur texte habituel.

Si votre navigateur web se trouve sous Mac ou Linux, vous devez ouvrir le fichier hosts qui se trouve dans /etc/host avec votre éditeur texte habituel.

Et on ajoute les lignes suivantes :

192.168.1.15 zendsite.com
192.168.1.15 www.zendsite.com

En prenant soin de changer l'IP pour celle de votre serveur.

Maintenant nous devons signaler au serveur que les requetes arrivant depuis le domaine zendsite.com devront être redirigées vers le dossier /www/htdocs/sitezend/html/.

Pour cela on créé un virtualhost :

$ nano /etc/apache2/sites-available/zendsite.com

Et on y colle notre virtualhost :

<VirtualHost *:80>
 ServerAdmin postmaster@zendsite.com
 ServerName zendsite.com
 ServerAlias www.zendsite.com
 DocumentRoot /www/htdocs/sitezend/html/
 <Directory /www/htdocs/sitezend/html/>
  Options -Indexes FollowSymLinks
  AllowOverride All
 </Directory>
 ErrorLog /htdocs/logs/zendsite_error.log
 LogLevel warn
 CustomLog /htdocs/logs/zend_site_access.log combined
 ServerSignature Off
</VirtualHost>

On enregistre et on quitte

On créé un dossier pour les logs :

$ mkdir /www/htdocs/logs/

On rend le domaine créé disponible :

$ ln -s /etc/apache2/sites-available/zendsite.com /etc/apache2/sites-enabled/zendsite.com

On redémarre apache :

$ /etc/init.d/apache2 restart

Le nom de domaine zendsite.com devrait maintenant nous rediriger vers le dossier html/ de notre serveur dans le lequel nous allons placer notre bootstrap que nous allons voir maintenant.


Correction de l'exercice 3

Voyons maintenant notre bootstrap (contrôleur frontal) :

$ nano /www/htdocs/sitezend/html/index.php
<?php

require_once 'Zend/Loader/Autoloader.php';
$loader = Zend_Loader_Autoloader::getInstance();
$loader->setFallbackAutoloader(true);

// Appel du contrôleur frontal,
// qui se charge de traiter la requête
Zend_Controller_Front::run('../application/controllers');

Puis notre controleur :

$ nano /www/htdocs/sitezend/application/controllers/IndexController.php
<?php

// La classe correspondant au contrôleur index
// (contrôleur par défaut)
class IndexController extends Zend_Controller_Action
{
    // L’action index
    public function indexAction()
    {

    }
}

Et enfin le contenu de notre vue :

$ nano /www/htdocs/sitezend/application/views/scripts/index/index.phtml
<?php

echo "Hello Zend!";

Testons notre application :

On remarque qu'en chargeant notre bootstrap, la vue est affichée


Correction de l'exercice 4

Pour pouvoir utiliser des contrôleurs, nous devons indiquer à notre serveur que nous ne ferons pas appel à de véritables dossiers présents sur le serveur mais que nous utiliserons la requête HTTP comme moyen de communication avec Zend.

Pour se faire, nous utilisons un .htaccess que nous allons créer :

$ nano /www/htdocs/sitezend/html/.htaccess

Et on colle nos règles de réécriture:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

On enregistre et on quitte.

On peut maintenant créer notre contrôleur login :

$ nano /www/htdocs/sitezend/application/controllers/LoginController.php

Et on créé nos fonctions :

<?php

class LoginController extends Zend_Controller_Action
{
    public function indexAction ()
    {

    }

    public function loginAction ()
    {

    }

    public function logoutAction ()
    {

    }

}

On créé le dossier login qui regroupera les vues de notre contrôleur fraîchement créé :

$ mkdir /www/htdocs/sitezend/application/views/scripts/login/

On créé le fichier index.phtml qui possédera la vue de l'index du contrôleur login :

$ nano /www/htdocs/sitezend/application/views/scripts/login/index.phtml

Et on colle un texte de test comme par exemple :

Vous êtes sur la vue index du contrôleur login

On vérifie en se rendant sur http://www.zendsite.com/login/, et on devrait avoir le résultat suivant :

Nous allons maintenant voir comment transmettre des paramètres à une vue depuis un contrôleur.

C'est très simple, nous devons utiliser la syntaxe suivante dans la fonction de notre contrôleur (application/controllers/LoginController.php) :

public function indexAction ()
{
    $this->view->title = 'Titre de la page';
}

Et on réceptionne les valeurs dans notre vue (application/views/scripts/login/index.phtml) de la manière suivante :

<?php echo $this->title; ?>

Et on peut constater que ça fonctionne correctement :


Correction de l'exercice 5

On ouvre notre script controllers/LoginController.php et on ajoute notre action (vide pour le moment):

public function mdpoublieAction ()
{

}

Et on créé notre vue dans views/scripts/login/mdpoublie.phtml :

$ nano /www/htdocs/sitezend/application/views/scripts/login/mdpoublie.phtml

On test en chargeant http://www.zendsite.com/login/mdpoublie/ depuis notre navigateur :


Correction de l'exercice 6

Dans Zend, les données superglobales GET, POST, COOKIE, SERVER, ENV se récupèrent avec getRequest()

On commence par envoyer la variable param contenant les variables prenom et nom définis en GET :

public function mdpoublieAction ()
{
    $G_nom = $this->getRequest()->nom;
    $G_prenom = $this->getRequest()->prenom;
    $this->view->param = $G_prenom.' '.$G_nom;
}

Dans notre vue, on affiche le paramètre param défini dans notre action.

<?php echo $this->param; ?>

On appel notre action dans le navigateur en indiquant nos paramètres GET http://www.zendsite.com/login/mdpoublie/prenom/paul/nom/danilo/

Pour aller encore plus vite nous pouvons utiliser getParam() pour récupérer les paramètres :

public function mdpoublieAction ()
{
    $G_nom = $this->getParam("nom");
    $G_prenom = $this->getParam("prenom");
    $this->view->param = $G_prenom.' '.$G_nom;
}

Il est nécessaire de maintenir dans l'esprit que le nom de propriété (clé du tableau des superglobales) est assorti à une superglobale dans un ordre spécifique de priorité : 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV.


Correction de l'exercice 7

Le principe est exactement le même qu'avec les paramètres GET.

On commence par compléter notre vue avec notre formulaire :

<form method="POST" action="">
 <input name="prenom" type="hidden" value="Paul" />
 <input name="nom" type="hidden" value="Danilo" />
 <input type="submit" value="Envoyer" />
</form>
<?php echo "Param : ".$this->param; ?>

Notez que l'on a ajouté l'affichage de la variable param envoyé depuis notre contrôleur pour vérifier que celui ci l'a bien reçu

Concernant notre contrôleur, rien ne change :

public function mdpoublieAction ()
{
    $G_nom = $this->getParam("nom");
    $G_prenom = $this->getParam("prenom");
    $this->view->param = $G_prenom.' '.$G_nom;
}

On test le tout en appelant l'URL http://www.zendsite.com/login/mdpoublie/ et en cliquant sur le bouton envoyer :

Nous voyons là un exemple concret sur comment Zend Framework peut nous permettre de gagner du temps et simplifier notre code.

Pour aller encore plus loin, notre formulaire html précédent aurait pu parfaitement être remplacé par :

<form method="POST" action="">
<?php
$this->formHidden("prenom", "Paul");
$this->formHidden("nom", "Danilo");
$this->formSubmit("envoyer", "Envoyer");
?>
</form>

Correction de l'exercice 8

Il est possible de factoriser des traitements communs effectués en début ou en fin de plusieurs actions grâce aux méthodes d’initialisation et de post-dispatching :

  • la méthode init() est appelée à la construction du contrôleur d’action.
  • la méthode preDispatch() est appelée avant chaque action.
  • la méthode postDispatch() est appelée après chaque action.

Dans notre contrôleur login on ajoute la méthode suivante :

public function init()
{
    $this->view->TitrePage = "Titre de ma page";
}

On modifie notre vue :

<html>
    <head>
        <?php echo $this->TitrePage; ?>
    </head>
    <body>
  
    </body>
</html>

On charge http://www.zendsite.com/login/mdpoublie/ pour vérifier le titre de la page est bien défini :


Correction de l'exercice 9

Il est courant que chaque page comporte des parties communes, telles que l'en-tête et le pied de page, le menu et les styles CSS. Zend_Layout va nous permettre de créer un gabarit qui nous évitera de dupliquer du code HTML d’une vue à l’autre.

Pour simplifier notre apprentissage, considérons que l’application ne comporte qu'un seul gabarit de page. Mais que cela ne nous limite pas dans l’absolu, il est bien sûr possible d’avoir plusieurs gabarits utilisés séparément ou en même temps.

Notre gabarit est composé de 4 parties principales :

  • Les paramètres situés dans la balise <head> de la page.
  • L'en-tête (header) de la page, comportant le titre et le formulaire de login.
  • Le contenu de la page (body), comprenant les données générées par la vue du contrôleur.
  • Le pied de page (footer), qui contiendra simplement une information de type copyright ou une signature.

Nous allons utiliser un gabarit pour notre méthode login.

Pour cela, on indique dans la fonction init() de la méthode login que nous utiliserons le gabarit layout.phtml situé dans application/views/login/

Zend_Layout::startMvc(array('layoutPath' => '../application/views/scripts/login/'));

Si nous voulons utiliser un autre gabarit dans une autre méthode du contrôleur login, il nous suffira de redéfinir Zend_Layout::startMvC()

On créé notre gabarit que l'on nomme layout.phtml :

$ nano /www/htdocs/sitezend/application/views/scripts/login/layout.phtml

On y place le code suivant :


<?php echo $this->doctype("XHTML1_TRANSITIONAL"), PHP_EOL; ?>


<?php  echo $this->headMeta()
->setHttpEquiv('Content-Type', 'text/html; charset=utf-8')
->setHttpEquiv('Content-Style-Type', 'text/css')
->setHttpEquiv('lang', 'fr')
->setHttpEquiv('imagetoolbar', 'no')
->setName('language', 'fr');
echo $this->headTitle($this->TitrePage);
echo $this->headLink(array('rel' => 'favicon', 'type' => 'image/x-icon', 'href' => 'images/favicon.ico'));
echo $this->headStyle()->appendStyle('@import "css/styles.css";');
?>


Notez la présence des appels $this->head*() qui sont des aides permettant d’écrire les données spécifiques contenues dans la balise <head> de l’application. Il existe des méthodes head*() spécifiques à différents types de balises : headMeta(), headLink(), headTitle(), headStyle()...

On peut déjà tester notre gabarit en affichant la source de http://www.zendsite.com/login/ :

Nous allons maintenant créer notre header et notre footer :

Pour cela rien de bien compliqué, nous allons commencer par créer un dossier common/ dans views/scripts/ qui contiendra les vues communes à nos pages

On créé le nouveau dossier common/ :

$ mkdir /www/htdocs/sitezend/application/views/scripts/common

Et notre header :

$ nano /www/htdocs/sitezend/application/views/scripts/common/header.phtml

On y insère le code html suivant :

<div style="float: right; padding-top: 3px">
    <a href="<?php echo $this->baseUrl(); ?>">Accueil | <a href="">Nous contacter |
</div>
<div style="padding-top: 3px">
    <?php echo $this->escape($this->TitrePage); ?>
</div>

Notez la présence de la fonction escape(), par défaut, elle utilise la fonction PHP htmlspecialchar() pour l'échappement. Cependant, en fonction de votre environnement, vous souhaitez peut-être un échappement différent. Utilisez la méthode setEscape() au niveau du contrôleur pour dire à Zend_View quelle méthode de rappel ("callback") elle doit utiliser.

Il nous reste maintenant à appeler le header depuis notre gabarit (layout). Pour cela nous allons utiliser la méthode $this->partial().

Avec partial, le contexte de la vue n'est pas celui du gabarit, d'où l'importance de transmettre les paramètres dynamiques, ce que nous avons fait avec le titre de la page :

<div id="header">
<?php echo $this->partial('common/header.phtml', array('TitrePage' => $this->TitrePage)); ?>
</div>

En chargeant différentes pages, nous remarquons que notre header apparaît bien :

Passons maintenant à notre footer où le principe est exactement identique :

On commence par créer le fichier common/footer.phtml

$ nano /www/htdocs/sitezend/application/views/scripts/common/footer.phtml

Puis son code html :

<div style="margin-top:25px; text-align:center;">© 2013 ZendSite.com - tous droits réservé

Que nous appelons dans notre gabarit :

<div id="footer">
<?php echo $this->partial('common/footer.phtml'); ?>
</div>

Et on vérifie via notre navigateur :

Il nous reste maintenant à charger la partie variable de notre gabarit, celle qui changera en fonction de l'URL chargée.

Rien de bien compliqué, il nous suffit d'appeler $this->layout()->content et le résultat de notre vue sera affiché

<div id="page">
<?php echo $this->layout()->content; ?>
</div>

Pour vérifier son bon fonctionnement, revenons à notre contrôleur login et notre méthode mdpoublie et nous allons lui demander de nous retourner les paramètres GET nom et prenom comme vu précédemment

public function mdpoublieAction ()
{
    $P_prenom = $this->getParam("prenom");
    $P_nom = $this->getParam("nom");
    $this->view->param = $P_prenom.' '.$P_nom;
}

Adaptons notre vue afin qu'elle nous retourne uniquement la variable param

<?php echo $this->param; ?>

Il nous reste plus qu'à utiliser notre navigateur pour vérifier le tout :

Nous pouvons constater que nos paramètres sont bien affichés ainsi que le gabarit qui va avec.

Aucun commentaire:

Enregistrer un commentaire