dimanche 3 mars 2013

Mise en cache

La mise en place d’une gestion de cache est un bon moyen d’économiser des ressources machines, idéal pour améliorer le confort de navigation des visiteurs.

On peut définir le cache comme un mécanisme dont le but est d’économiser des ressources en supprimant les traitements redondants. Typiquement, le cache permet d’éviter de générer une page dynamique plusieurs fois, dans la mesure ou celle-ci ne change pas d’un appel à l’autre.

Mais on peut aller plus loin avec le cache : tout d’abord, en mettant en cache non pas une page, mais une partie de page (cache partiel). Enfin, on retrouve le cache sur plusieurs niveaux : le plus bas niveau concerne la mise en cache du code compilé de PHP et le plus haut, la mise en cache des pages. Entre les deux, il est possible de mettre en cache des retours de fonctions, des blocs d’information ou des objets.

Exercice 1 : Installation d'APC

1) Vérifiez la présence du paquet php-apc sur votre serveur.

2) Installez le paquet php-apc si celui ci n'est pas encore présent.

3) Trouvez et copiez le fichier apc.php dans /www/htdocs/sitezend_avance/html/

4) Affichez la page de monitoring apc.php


Exercice 2

1) Créez le fichier /www/library/class/ZendCache.php et ajoutez y le code PHP de l'annexe 1.


Exercice 3

1) Chargez la class ZendCache créée dans l'exercice 2 dans le bootstrap.


Exerice 4

1) Créez un script PHP et vérifiez que le cache fonctionne correctement.


Exercice 5

1) Mettez en cache l'opcode de votre application


Annexe 1

class Library_Class_ZendCache
{
    private static $_cache = null;
    private static $_lifetime = 3600;
    private static $_cacheDir = null;

    private static function init() {

        if (self::$_cache === null) 
        {
            $frontendOptions = array('automatic_serialization' => true, 'lifetime' => self::$_lifetime);
            $backendOptions = array('cache_dir', self::$_cacheDir);
   
            try {
                if (extension_loaded('APC'))
                {
                    self::$_cache = Zend_Cache::factory('Core', 'APC', $frontendOptions, array());
                }
                else
                {
                    self::$_cache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
                }
            }
            catch (Zend_Cache_Exception $e)
            {
                    throw new Zend_Exception($e);
            }

            if (!self::$_cache) 
            {
                throw new Zend_Exception("No cache backend available.");
            }
   
        }

    }

    public static function setup($lifetime, $filesCachePath = null) {

        if (self::$_cache !== null)
        {
            throw new Zend_Exception("Cache already used.");
        }

        self::$_lifetime = (integer) $lifetime;

        if ($filesCachePath !== null)
        {
            self::$_cacheDir = realpath($filesCachePath);
        }

    }

    public static function set($data, $key) {

        self::init();
        return self::$_cache->save($data, $key);

    }

    public static function get($key) {

        self::init();
        return self::$_cache->load($key);
  
    }

    public static function clean($key = null) {

        self::init();

        if ($key === null)
        {
            return self::$_cache->clean();
        }

        return self::$_cache->remove($key);

    }

    public static function getCacheInstance() {

        if (is_null(self::$_cache))
        {
            throw new Zend_Exception("Cache not set yet.");
        }

        return self::$_cache;

    }
}

Correction de l'exercice 1

Pour commencer, on vérifie que le paquet php-apc n'est pas déjà installé sur notre serveur. On éxécute pour cela la commande suivante :

$ apt-cache policy php-apc

Si on obtient le résultat suivant c'est que APC n'est pas encore installé :

Pour l'installer c'est simple :

$ apt-get install php-apc

Pour vérifier que l'installation c'est bien déroulée, rendez-vous dans le phpinfo et vérifiez la présence d'APC :

Lors de l'installation d'APC, un script de monitoring a été fourni. Nous allons le trouver et le copier dans notre dossier de travail.

Pour trouver un fichier à partir de son nom (apc.php) sur debian, nous allons utiliser la commande suivante :

$ find / -name apc.php* 2>/dev/null

Ce qui devrait nous retourner le résultat suivant :

Le fichier qui nous intéresse est /usr/src/APC-3.1.8/apc.php

La commande cp va nous permettre de le copier dans notre répertoire de travail.

cp /usr/src/APC-3.1.8/apc.php /www/htdocs/sitezend_avance/html/

On test en chargeant apc.php depuis notre navigateur :


Correction de l'exercice 2

On commence par créer notre dossier class dans library :

$ mkdir /www/library/class/

Puis on créé le fichier ZendCache.php

$ nano /www/library/class/ZendCache.php

Et on y colle notre class :

On enregistre et on quitte


Correction de l'exercice 3

Maintenant nous devons indiquer à notre application de charger la class que nous venons de créer.

Pour cela on fait appel à notre bootstrap dans lequel nous allons ajouter un objet Zend_Loader_Autoloader_Resource comme vu précédement pour ajouter un modèle.

$ nano /www/htdocs/sitezend_avance/application/Bootstrap.php

Dans lequel nous allons ajouter la fonction suivante à la suite.

protected function _initCache () {
 
 $resourceLoader = new Zend_Loader_Autoloader_Resource(array(
  'basePath'  => '/www/library',
  'namespace' => 'Library',
 ));

 $resourceLoader->addResourceType('class', 'class/', 'Class');
 
}

Correction de l'exercice 4

Passons maintenant aux tests. Nous allons faire nos tests dans le contrôleur index.

$ nano /www/htdocs/sitezend_avance/application/controllers/IndexController.php

Et dans la méthode indexAction() on ajoute :

public function indexAction() {
 
 $reservations = Library_Class_ZendCache::get('reservations');
  
 if (!$reservations)
 {
  $reservations = 'Chaine contenant les réservation'.' date: '.time();
   
  Library_Class_ZendCache::set($reservations, 'reservations');
  
  echo 'Inséré dans le cache : '.$reservations;
 }
 else
 {
  echo $reservations;
 }
  
}

Lors du premier affichage vous devriez avoir :

Le cache reservation n'est pas disponible, donc il met notre chaine en cache sous le nom réservation.

Puis lors du second rechargement :

Le cache est maintenant disponible il choisi donc de l'afficher.


Correction de l'exercice 5

Il faut savoir qu'actuellement, lorsque vous chargez un script PHP, les étapes suivantes font s’exécuter :

  • Chargement du script PHP depuis le disque dur
  • Compilation du script PHP (op-code)
  • Exécution de la compilation par PHP
  • Affichage du résultat

Le cache APC va nous permettre de mettre directement la compilation de nos pages PHP en mémoire RAM, ainsi au lieu de charger nos pages depuis le disque dur et de devoir les interpréter à chaque fois, il chargera des version compilé depuis la mémoire RAM ce qui nous fera gagner un temps précieux.

Pour commencer il nous faut connaitre la taille de notre application (Zend Framework compris), pour nous il s'agit du /www/. Pour cela on utilise la commande du :

$ du -sh /www/

L'option -s permet d'afficher que le total (et non la taille de chaque sous-dossier). L'option -h permet d'afficher un résultat lisible par humain (en non pas en kio)

On obtient un résultat de 42M. On va multiplier ce résultat par 1,5 car l'op-code est environ 1,5 fois plus dense que le code PHP brut. Donc 42 x 1,5 = 63.

Indiquons à APC qu'il peut utiliser jusqu'à 63 Mio de mémoire pour mettre en cache les fichiers.

Pour savoir où se trouve le fichier de configuration, nous allons afficher notre phpinfo()

Maintenant que nous savons où se trouve notre fichier de configuration il ne nous reste plus qu'à le modifier :

$ nano /etc/php5/apache2/conf.d/apc.ini

Et on rajoute apc.shm_size = 63 dans notre fichier.

On enregistre et on quitte.

On redémarre Apache pour prendre en compte les modifications :

$ /etc/init.d/apache2 restart

On revient sur la page de monitoring :

Et on peut apercevoir que la nouvelle taille du cache a été prise en compte.

Maintenant nous allons mettre notre application en cache :

Pour commencer on va créer le fichier /www/htdocs/sitezend_avance/html/compil_apc.php et y coller le code suivant :

class MyFilterIterator extends FilterIterator
{
 public function accept() {
  
  if (substr($this->current(), - 3) == 'php')
  {
   return $this->current();
  }
  
 }
}

$rdi = new RecursiveDirectoryIterator('/www/');
$rii = new RecursiveIteratorIterator($rdi, RecursiveIteratorIterator::LEAVES_ONLY);

apc_clear_cache();

foreach (new MyFilterIterator($rii) as $file)
{
 if (apc_compile_file($file->getPathname()))
 {
  echo "OK : apc_compile_file(".$file.")\n";
 }
 else
 {
  echo "ERROR : apc_compile_file(".$file.")\n";
 }
}

Et on l'éxécute :

A priori tout c'est déroulé correctement. Revenons au monitoring APC :

On peut s'apercevoir que le cache est maintenant rempli et qu'il contient 2 527 fichiers.

Vérifiez de temps à autres qu'il reste de la mémoire pour APC et que le taux de hit (appel caché) et supérieur au taux de miss (appel non caché).

Internationalisation

À l’heure de la mondialisation, l’internationalisation s’impose comme un enjeu essentiel. Elle implique la gestion de nombreux détails susceptibles de devenir de vrais casse-tête : jeux de caractères, changement de langue, gestion des monnaies, synchronisation des horloges, etc. Prévenir plutôt que guérir, voilà pourquoi il est essentiel de penser en amont votre internationalisation.

Exercice 1

1) Créez le fichier /www/htdocs/sitezend_avance/application/config/traduction.tmx qui contiendra les traductions suivantes au format tmx :

Bonjour : Bonjour (fr), Buenos dias (es), Hello (en)
Exemple de traduction : Traduction example (en)

2) Dans la méthode indexAction() du contrôleur index, affichez le texte Bonjour traduit en anglais.


Correction de l'exercice 1

$ nano /www/htdocs/sitezend_avance/application/config/traduction.tmx
<?xml version="1.0" ?>
<!DOCTYPE tmx SYSTEM "tmx14.dtd">
<tmx version="1.4">
    <header creationtoolversion="1.0.0"
    datatype="winres"
    segtype="sentence"
    adminlang="fr-fr"
    srclang="fr-fr"
    o-tmf="abc"
    creationtool="XYZTool" />
    <body>
        <tu tuid='Bonjour'>
            <tuv xml:lang="fr">Bonjour
            <tuv xml:lang="es">Buenos dias
            <tuv xml:lang="en">Hello
        </tu>
        <tu tuid='Exemple de traduction'>
            <tuv xml:lang="en">Traduction example
        </tu>
    </body>
</tmx>

On déclare notre fichier de traduction dans notre bootstrap en créant la fonction _initTrad() :

$ nano /www/htdocs/sitezend_avance/application/Bootstrap.php
protected function _initTrad () {
 
    // Déclaration de l’objet translate
    $translate = new Zend_Translate('tmx', APPLICATION_PATH.'/config/traduction.tmx', 'fr');
    // Enregistrement explicite de la langue courante
    $translate->setLocale('fr');

    Zend_Registry::set('trad', $translate);
  
}

Retournons dans notre contrôleur index :

$ nano /www/htdocs/sitezend_avance/application/controllers/IndexController.php

Dans la méthode init() on récupère l'objet trad créé dans le bootstrap :

public function init() {

    $this->translate = Zend_Registry::get('trad');

}

Et dans notre méthode indexAction() on affiche la traduction

public function indexAction() {

    echo $this->translate->_('Bonjour');

}

On affiche notre site et on devrait obtenir le résultat suivant :

Il est vrai que cet exemple n'est pas le plus parlant, revenons à notre bootstrap pour la méthode _initTrad() que nous avons créé au dessus.

Et on change :

$translate->setLocale('fr');

pour :

$translate->setLocale('en');

Et on recharge notre page :

Notre chaîne est correctement traduite en anglais.

Sessions et cookies

Exercice 1

1) Déclarer la variable de SESSION CodeUser dans l'espace de nom user et donnez lui 125 comme valeur.


Exercice 2

1) Détruisez la variable de SESSION créée dans l'exercice 1.


Exercice 3

1) Créez le COOKIE TestCookie et donnez lui pour valeur la chaîne "valeur du cookie". Le COOKIE doit être disponible pendant 1 heure.


Exercice 4

1) Détruisez le cookie créé dans l'exercice 3.


Correction de l'exercice 1

Avec Zend, l'utilisation des SESSION passe par l'utilisation de Zend_Session_Namespace

Les instances Zend_Session_Namespace fournissent l'API primaire pour manipuler les données de session dans Zend Framework. Les espaces de noms sont utilisés pour isoler toutes les données de session, bien qu'un espace de noms par défaut existe pour ceux qui veulent juste un endroit pour stocker toutes leurs données de session.

$ nano /www/htdocs/sitezend_avance/application/controllers/IndexController.php
public function indexAction()
{
    $session = new Zend_Session_Namespace('user');
    $session -> CodeUser = 125;

    if ($session -> CodeUser)
    {
        echo 'SESSION : '.$session -> CodeUser;
    }
    else
    {
        echo 'PAS DE SESSION';
    }
}

Mettons en commentaire la déclaration de notre variable CodeUser :

public function indexAction()
{
    $session = new Zend_Session_Namespace('user');
    // $session -> CodeUser = 125;

    if ($session -> CodeUser)
    {
        echo 'SESSION : '.$session -> CodeUser;
    }
    else
    {
        echo 'PAS DE SESSION';
    }
}

On recharge la page et on peut constater que notre session est toujours présente.


Correction de l'exercice 2

Pour détruire notre SESSION nous allons tout simplement utiliser la fonction unset() :

public function indexAction()
{
    $session = new Zend_Session_Namespace('user');
    unset($session -> CodeUser);

    if ($session -> CodeUser)
    {
        echo 'SESSION : '.$session -> CodeUser;
    }
    else
    {
        echo 'PAS DE SESSION';
    }
}

On charge notre page pour vérifier que la session a bien été détruite :


Correction de l'exercice 3

Passons maintenant aux cookies, pour cela nous allons tout simplement utiliser la fonction setcookie() de php :

$ nano /www/htdocs/sitezend_avance/application/controllers/IndexController.php
public function indexAction()
{
    setcookie("TestCookie", 'valeur du cookie', time()+3600);  /* expire dans 1 heure */

    if ($this->getRequest()->getCookie('TestCookie'))
    {
        echo 'COOKIE : ' . $this->getRequest()->getCookie('TestCookie');
    }
    else
    {
        echo 'PAS DE COOKIE';
    }
}

Nous pouvons également récupérer la valeur de notre cookie en faisant un $this->getRequest()->TestCookie, attention toutefois que le nom TestCookie ne soit pas utilisé par une autre variable GET ou POST car le cookie arrive en 3ème position

public function indexAction()
{
    setcookie("TestCookie", 'valeur du cookie', time()+3600);  /* expire dans 1 heure */

    if ($this->getRequest()->TestCookie)
    {
        echo 'COOKIE : ' . $this->getRequest()->TestCookie;
    }
    else
    {
        echo 'PAS DE COOKIE';
    }
}

On test ça en chargeant notre page, pensez à bien charger votre page 2 fois car le cookie est mis en mémoire à un niveau supérieur de notre fonction.

Ce cookie sera disponible pendant 1 heure.


Correction de l'exercice 4

Pour effacer un cookie sur le client, vous devez toujours vous assurer que sa date d'expiration est passée, pour déclencher le mécanisme du navigateur client. Voici comment procéder :

public function indexAction()
{
    setcookie("TestCookie", '', time()-3600);

    if ($this->getRequest()->TestCookie)
    {
        echo 'COOKIE : ' . $this->getRequest()->TestCookie;
    }
    else
    {
        echo 'PAS DE COOKIE';
    }
}

On test et on devrait obtenir le résultat suivant (là encore on doit charger 2 fois la page) :

Architecture MVC avancée

Exercice 1 : Une nouvelle application

1) Créez le dossier /www/htdocs/sitezend_avance/ ainsi qu'un squelette MVC.

2) Redirigez le virtual user zendsite.com vers ce nouveau dossier.

3) Toujours dans le virtual user, ajoutez la variable d’environnement APPLICATION_ENV ayant pour valeur development.


Exercice 2 : Configuration et bootstrap

1) Créez le fichier de configuration /www/htdocs/sitezend_avance/application/config/application.ini.

2) Créez le fichier bootstrap /www/htdocs/sitezend_avance/html/index.php qui prend en compte le fichier de configuration application.ini.


Exercice 3 : class bootstrap : config.ini

1) Créez le fichier /www/htdocs/sitezend_avance/application/Bootstrap.php qui contiendra la class Bootstrap.

2) A l'aide de l'annexe 1, créez le fichier de configuration /www/htdocs/sitezend_avance/application/config/config.ini

3) Dans la class bootstrap, créez la méthode d'initialisation _initConfigVars() qui se chargera de charger le fichier config.ini et le rendre disponible dans toute notre application.


Exercice 4 : class bootstrap : Connexion avec la base de données

1) Dans la class bootstrap, créez la méthode d'initialisation _initDb() ayant pour de créer la connexion avec la base de données et la rendre disponible dans toute notre application.


Exercice 5 : Les modèles

1) Dans la class bootstrap, créez la méthode d'initialisation _initModels() ayant pour but de charger les modèles du dossier models/

2) En reprenant le modèle TUser du chapitre 1.4, créez le modèle Application_Model_TUser dans /www/htdocs/sitezend_avance/application/models/TUser.php

3) Utilisez le modèle pour afficher la liste des admin dans le contrôleur index.

4) Toujours en utilisant le modèle Application_Model_TUser, afficher les infos de l'utilisateur ayant pour clé primaire 1


Exercice 6 : Les helpers

1) Créez le dossier /www/htdocs/sitezend_avance/application/controllers/helpers/ qui contiendra nos helpers

2) En utilisant l'annexe 2, créez le helper Menu dans /www/htdocs/sitezend_avance/application/controllers/helpers/Menu.php

3) Chargez votre dossier helpers dans la class bootstrap.

4) Afficher le menu dans le contrôleur index.


Annexe 1

[production]
var1 = blabla_prod_1
var2 = blabla_prod_2

; MAIL
mail.value = paul@zendsite.fr

[development : production]
var1 = blabla_dev_1
var2 = blabla_dev_2

Annexe 2

class Zend_Controller_Action_Helper_Menu extends Zend_Controller_Action_Helper_Abstract
{
    public function menu_gauche ()
    {
        return '';
    }
}

Correction de l'exercice 1

Maintenant que nous avons vu à quoi servait globalement l'architecture MVC nous allons aller un peu plus loin.

Nous allons commencer par créer le squelette de notre nouvelle application zend dans un dossier sitezend_avance/ :

mkdir /www/htdocs/sitezend_avance/
Puis les autres dossiers nécessaires à notre application :
mkdir /www/htdocs/sitezend_avance/
mkdir /www/htdocs/sitezend_avance/application/
mkdir /www/htdocs/sitezend_avance/application/config/
mkdir /www/htdocs/sitezend_avance/application/controllers/
mkdir /www/htdocs/sitezend_avance/application/models/
mkdir /www/htdocs/sitezend_avance/application/views/
mkdir /www/htdocs/sitezend_avance/application/views/layouts/
mkdir /www/htdocs/sitezend_avance/application/views/scripts/
mkdir /www/htdocs/sitezend_avance/application/views/scripts/common/
mkdir /www/htdocs/sitezend_avance/application/views/scripts/index/
mkdir /www/htdocs/sitezend_avance/html/

Modifions maintenant notre virtualuser afin qu'il pointe vers notre nouveau dossier /www/htdocs/sitezend_avance/

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

puis on modifie les lignes suivantes :

DocumentRoot /www/htdocs/sitezend/html/
<Directory /www/htdocs/sitezend/html/>

pour :

DocumentRoot /www/htdocs/sitezend_avance/html/
<Directory /www/htdocs/sitezend_avance/html/>

Nous allons également profiter d'être dans le virtualhost pour ajouter le paramètre suivant :

SetEnv APPLICATION_ENV "development"

Ainsi notre virtualhost enverra la variable APPLICATION_ENV à PHP ayant pour valeur development


Correction de l'exercice 2

Passons maintenant à la mise en place de notre bootstrap qui est cette fois ci plus complexe

Nous l'avons vu dans le chapitre précédent, le bootstrap est le fichier qui va être lancé au début de l’application, la grande majorité des pages que chargerons seront aiguillées par le bootstrap

Nous allons nous charger de l'améliorer un peu pour qu'il puisse maintenant s’occuper d’exécuter toutes les petites routines, de faire les connections aux bases de données, d’instancier toutes les constantes, les sessions, les modules, les layouts etc ...

On va créer le fichier de configuration sur lequel nous définissons nos constantes :

$ nano /www/htdocs/sitezend_avance/application/config/application.ini

Puis on colle le paramètres suivants

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.useDefaultControllerAlways = true
resources.frontController.defaultControllerName = "index"
resources.frontController.defaultAction = "index"

;DB
resources.db.adapter = "Pdo_Mysql"
resources.db.isDefaultTableAdapter = true
resources.db.params.charset = "utf8"
resources.db.params.host = "localhost"
resources.db.params.username = "zenduser"
resources.db.params.password = "qp56"
resources.db.params.dbname = "zendbdd"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

Notez que nous avons repris la base de données créée dans le chapitre précédent

Occupons nous maintenant de notre bootstrap avec lequel nous allons appeler le fichier .ini que nous venons de créer

$ nano /www/htdocs/sitezend_avance/html/index.php

Puis on colle le code du bootstrap :

<?php
 
// On défini le chemin de notre application dans la variable APPLICATION_PATH
defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__)) . '/../application');
 
// Si la variable APPLICATION_ENV n'est pas définie on lui donne la valeur 'production', la notre est renseignée dans le virtualhost sur 'development'
defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production'));
 

/** On appel Zend_Application */
require_once 'Zend/Application.php';
 
// On créé le bootstrap et on le lance
$app = new Zend_Application(APPLICATION_ENV, APPLICATION_PATH.'/config/application.ini');
$app->bootstrap()->run();

Correction de l'exercice 3

Notre bootstrap nous permet désormais de créer la class Bootstrap afin de pouvoir réaliser différents processus

On créé donc le fichier Bootstrap.php (son chemin a été défini dans le fichier application.ini précédemment créé) :

$ nano /www/htdocs/sitezend_avance/application/Bootstrap.php

Et on commence par coller les instructions suivantes :

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    public function run()
    {
        Zend_Registry::set('config', new Zend_Config($this->getOptions()));
        parent::run();
    }
}

Nous allons maintenant pouvoir créer des méthodes dans notre class Bootstrap afin qu'il réalise quelques routines

Commençons par le chargement de notre fichier de configuration config.ini que nous allons créer.

Nous l'avons vu dans le chapitre précédent, les fichiers .ini contiennent des constantes que nous pouvons modifier à tout moment

$ nano /www/htdocs/sitezend_avance/application/config/config.ini

dans le lequel nous allons mettre quelques paramètres à titre d'exemple

[production]
var1 = blabla_prod_1
var2 = blabla_prod_2

; MAIL
mail.value = paul@zendsite.fr

[development : production]
var1 = blabla_dev_1
var2 = blabla_dev_2

Puis dans notre bootstrap nous ajoutons la méthode suivante :

protected function _initConfigVars() {

    $config = new Zend_Config_Ini(APPLICATION_PATH.'/config/config.ini', APPLICATION_ENV);
    Zend_Registry::set('config_vars', $config);

}

Toutes les méthodes commençant par _init seront chargées dans le bootstrap, à vous de voir quels noms vous préférez leurs donner.

On test en appelant une variable dans notre vue index :

Tout d'abord dans notre contrôleur

class IndexController extends Zend_Controller_Action
{
    // L’action index
    public function indexAction()
    {
        $config_vars = Zend_Registry::get('config_vars');
        $this->view->mail = $config_vars->mail->value;
        $this->view->var1 = $config_vars->var1;
        $this->view->var2 = $config_vars->var2;
    }
}

Il nous reste plus qu'à appeler nos variables dans notre vue

<?php echo 'variable : '.$this->mail.', var1 = '.$this->var1.', var2 = '.$this->var2; ?>

Ce qui devrait nous donner le résultat suivant :

Notez que nous récupérons les variables de développement car nous avons défini la variable APPLICATION_ENV sur development dans notre virtualhost

Notre code a été volontairement simplifié, cependant dans notre cas, l'utilisation de la méthode init() dans notre class IndexController aurait été judicieux :

<?php

class IndexController extends Zend_Controller_Action
{
    public function init()
    {
        $this->config_vars = Zend_Registry::get('config_vars');
    }
 
    public function indexAction()
    {
        $this->view->mail = $this->config_vars->mail->value;
        $this->view->var1 = $this->config_vars->var1;
        $this->view->var2 = $this->config_vars->var2;
    }
}

Correction de l'exercice 4

NB : Dans cet exercice nous allons réutiliser la base de données du chapitre précédent

Servons nous maintenant de notre bootstrap pour créer la connexion avec la base de données

protected function _initDb() {

    $config = new Zend_Config($this->getOptions());

    try {
        $db = Zend_Db::factory($config->resources->db);
        $db->getConnection();
    } catch (Exception $e) {
        exit($e->getMessage());
    }
 
    Zend_Db_Table_Abstract::setDefaultAdapter($db);
    Zend_Registry::set('database', $db);
    return $db;
 
}

Correction de l'exercice 5

Attaquons-nous maintenant aux modèles de notre architecture MVC.

Un modèle c'est quoi ?

Les modèles sont des class qui ne contiendront que des fonctions. Un modèle a pour but de gérer l'organisation des données. Chacune de ces fonctions effectuera une action bien précise. Nous ne pourrons effectuer des requêtes SQL que dans ces fonctions. Cela inclut aussi bien MySQL, que PostegreSQL, ou tout autre SGBDR. De même, les bases de données ne sont pas le seul moyen de gérer des données. Le modèle pourra donc tout aussi bien contenir des fonctions gérant des fichiers XML, par exemple.

Nous allons commencer par créer le modèle user qui s'occupera de gérer toutes les informations relatives aux utilisateurs de notre base de données.

Nous avons actuellement la structure suivante :

- /www/htdocs/sitezend_avance/application/
- - config/
- - controllers/
- - models/
- - views/

Au sein de ce répertoire, nous allons préfixer les class par l'espace de noms "Application_". Dans le dossier "models", le préfixe de composant "Model_" sera ajouté, ce qui nous donnera un nom de classe final "Application_Model_NomClass".

Pour configurer tout ça, revenons à notre bootstrap :

$ nano /www/htdocs/sitezend_avance/application/Bootstrap.php

Et ajoutons la fonction _init suivante :

protected function _initModels () {
    $resourceLoader = new Zend_Loader_Autoloader_Resource(array(
        'basePath'  => APPLICATION_PATH.'/',
        'namespace' => 'Application',
    ));
    $resourceLoader->addResourceType('model', 'models/', 'Model');
}

Ainsi quand nous créerons un objet Application_Model_TUser, Zend ira automatiquement chercher sa class dans application/models/TUser.php

Maintenant que l'appel des class modèles est configuré nous pouvons créer notre class

$ nano /www/htdocs/sitezend_avance/application/models/TUser.php

Dans lequel nous allons créer la class Application_Model_TUser :

<?php 
class Application_Model_TUser extends Zend_Db_Table_Abstract
{
     
}

Zend_Db_Table_Abstract vous dit quelque chose ? Oui nous l'avons déjà utilisé dans le chapitre 1 dans 1.4 Accès aux bases de données et nous allons tous simplement reprendre le travail effectué pour la class TUser :

<?php 
class Application_Model_TUser extends Zend_Db_Table_Abstract
{
    protected $_name = 'user';
    protected $_primary = 'userID';
 
    public function InfosUser ($pID) {
   
        $membres = $this->find($pID);
        $membre = $membres->current();
 
        return $membre->userPrenom.' '.$membre->userNom.'</br>';
   
    }
 
    public function recupAdmin () {
   
        $sql = "SELECT userNom FROM user WHERE userIsAdmin = 1";
        $user = $this->getAdapter()->fetchAll($sql, null, Zend_Db::FETCH_OBJ);
        return $user;
 
    }
}

Vérifions que tout cela fonctionne en utilisant notre contrôleur Index :

$ nano /www/htdocs/sitezend_avance/application/controllers/IndexController.php

Et modifions tous simplement la fonction indexAction :

public function indexAction()
{
    $resultat = '';
    $table = new Application_Model_TUser;
    $users = $table -> recupAdmin();
    foreach ($users as $user)
    {
        $resultat .= $user->userNom.'</br>';
    }
    $this->view->lesAdmin = $resultat;
}

Et adaptons notre vue pour qu'elle nous retourne le résultat de notre fonction :

$ nano /www/htdocs/sitezend_avance/application/views/scripts/index/index.phtml
<?php echo 'Les admin sont : <b>'.$this->lesAdmin.'</b>';

Et nous devrions avoir le résultat suivant :

Modifions la fonction InfosUser de la class Application_Model_TUser afin qu'elle nous retourne un objet :

public function InfosUser ($pID) {

    return $this->find($pID)->current();

}

Ainsi pour récupérer le prénom d'un utilisateur il nous suffira tout simplement d'appeler dans notre fonction :

$this->view->user = $table->InfosUser(1)->userPrenom;

Il nous reste plus qu'a afficher la variable user dans notre vue :

<?php echo 'Les admin sont : <b>'.$this->lesAdmin.'</b><br/>L\'utilisateur 1 : '.$this->user;

pour obtenir le résultat suivant :


Correction de l'exercice 6

Les helpers (ou aide d'action) sont des méthodes que nous pouvons appeler depuis n'importe quel contrôleur de notre application.

On commence par créer le dossier qui contiendra nos aides d'actions (helpers) :

mkdir /www/htdocs/sitezend_avance/application/controllers/helpers/

On créé notre helper Menu.php

nano /www/htdocs/sitezend_avance/application/controllers/helpers/Menu.php

Dans lequel nous mettons le code suivant :

<?php

class Zend_Controller_Action_Helper_Menu extends Zend_Controller_Action_Helper_Abstract
{
    public function menu_gauche ()
    {
        return '';
    }
}

On indique à notre bootstrap que le dossier que nous venons de créer contiendra nos helpers :

protected function _initHelpers () {
 Zend_Controller_Action_HelperBroker::addPath(APPLICATION_PATH.'/controllers/helpers/');
}

Notre bootstrap devrait ressembler à ça maintenant :

On indique à notre contrôleur d'envoyer le helper à notre vue :

public function indexAction()
{
    $this->view->menu = $this->_helper->menu->menu_gauche();
}

Que nous appelons bien évidemment dans la vue :

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

Le navigateur devrait nous renvoyer le résultat suivant :

A vous maintenant d'utiliser les helpers à bon escient.

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.