dimanche 3 mars 2013

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.

Aucun commentaire:

Enregistrer un commentaire