Débuter avec Zend Framework (approche MVC)

Cet article est la traduction de l'excellent tutoriel de Rob Allen : Getting started with the Zend Framework (Document Revision 1.6.3).

Commentez : 23 commentaires Donner une note à l'article (4.5)

Ce cours est une introduction à l'utilisation du Zend Framework, en créant une application très simple utilisant une base de données basée sur le paradigme Modèle-Vue-Contrôleur.

Ce tutoriel a été testé avec les versions 1.8 et 1.9 du Zend Framework. Il a de bonnes chances de fonctionner avec des versions plus récentes de la série 1.x, mais il ne fonctionnera pas avec des versions antérieures à la 1.8. La traduction du tutoriel équivalent pour les versions antérieures du Zend Framework est toujours disponible : Débuter avec Zend Framework 1.5 (approche MVC).

Article lu   fois.

Les deux auteurs

Site personnel

Site personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Pré-requis

Le Zend Framework a besoin des éléments suivants :
  • PHP 5.2.4 (ou ultérieur) ;
  • Un serveur Web supportant le mod_rewrite ou une fonctionnalité équivalente.

II. Pré-suppositions

J'ai supposé que vous utilisiez PHP 5.2.4 ou ultérieur avec le serveur web Apache. Votre installation d'Apache doit avoir l'extension mod_rewrite installée et configurée.

Vous devez également vous assurer qu'Apache est configuré pour accepter les fichiers .htaccess. Cela se fait habituellement en modifiant l'instruction AllowOverride None à AllowOverride All dans votre fichier httpd.conf.

Vérifiez les détails exacts dans la documentation de votre distribution. Vous ne pourrez naviguer sur aucune autre page que la page d'accueil si vous n'avez pas convenablement configuré l'utilisation de mod_rewrite et .htaccess.

III. Récupérer le framework

Le Zend Framework peut être téléchargé à l'adresse http://framework.zend.com/download au format .zip ou .tar.gz. Regardez en bas de page pour des liens directs.

IV. Configurer Zend_Tool

Le Zend Framework est fourni avec un nouvel outil en ligne de commandes. Nous commençons par le configurer. (1)

IV-A. Zend_Tool pour Windows

Zend_Tool dans la version 1.9.0 du Zend_Framework ne fonctionne pas sous Windows. Utilisez la version 1.8.4p1 à partir des archives à http://framework.zend.com/download/archives en attendant la version 1.9.1. (2)

  • Créez un nouveau répertoire dans Program Files appelé ZendFrameworkCli
  • Double-cliquez sur le fichier archive téléchargé, ZendFramework-1.8.4PL1-minimal.zip
  • Copiez les répertoires bin et library du dossier ZendFramework-1.8.4PL1-minimal.zip vers le répertoire C:\Program Files\ZendFrameworkCli. Ce répertoire doit maintenant avoir deux sous-répertoires : bin et library.
  • Ajoutez le répertoire library à votre path :
    • Allez à la section Système du Panneau de Configuration.
    • Choisissez Avancé et appuyez sur le bouton Variables d'Environnement.
    • Dans la liste des "Variables système", trouvez la variable Path et double-cliquez dessus.
    • Ajoutez ;C:\Program Files\ZendFrameworkCli\bin à la fin de la zone de saisie et appuyez sur Ok(3)
    • Redémarrez

IV-B. Zend_Tool pour OS X (similaire sous Linux)

  • Décompressez l'archive téléchargée, ZendFramework-1.9.0-minimal.zip dans votre répertoire Downloads en double-cliquant dessus.
  • Copiez-la vers /usr/local/ZendFrameworkCli en ouvrant un Terminal et en y saisissant :
    sudo cp -r ~/Downloads/Zendframework-1.9.0-minimal /usr/local/ZendFrameworkCli
  • Modifier votre profil bash pour ajouter un alias :
    • Depuis le Terminal, tapez : open ~/.bash_profile
    • Ajoutez alias zf=/usr/local/ZendFrameworkCli/bin/zf.sh à la fin du fichier
    • Sauvegardez et fermez TextEdit.
    • Quittez le Terminal

IV-C. Tester Zend_Tool

Vous pouvez tester votre installation de l'interface en ligne de commande Zend_Tool en ouvrant un Terminal ou une Invite de Commande et en tapant :

 
Sélectionnez
zf show version

Si tout fonctionne, vous devriez voir :

 
Sélectionnez
Zend Framework Vesrion : 1.9.0

Si ce n'est pas le cas, vérifiez que vous avez correctement défini votre path et que le répertoire bin existe bien dans le dossier ZendFrameworkCli.

V. Poser les fondations de notre application

Tous les éléments étant en place, nous pouvons construire une application avec le Zend Framework. Nous allons construire un système d'inventaire très simple pour exposer notre collection de CD. La page principale listera notre collection et nous permettra d'ajouter, modifier ou supprimer des CDs. Nous stockerons notre liste dans une base de données avec un schéma très simple comme ça :

Nom de champs Type Null ? Notes
id integer Non Clé primaire, auto-incrémentée
artiste varchar(100) Non  
titre varchar(100) Non  

Les pages suivantes seront nécessaires :

Page d'accueil Elle affichera la liste des albums avec des liens permettant de les modifier et de les supprimer. Un lien permettant d'ajouter de nouveaux albums sera aussi proposé.
Ajouter un nouvel album Cette page proposera un formulaire pour ajouter un nouvel album.
Modifier l'album Cette page proposera un formulaire pour modifier un album.
Supprimer l'album Cette page confirmera que vous voulez supprimer un album et le supprimera.

V-A. Créer le projet

Ouvrez un terminal ou une invite de commandes et allez dans le répertoire racine de votre serveur web en utilisant la commande cd. Assurez-vous d'avoir la permission de créer des fichiers dans ce répertoire et que le serveur web a le droit de lecture. Entrez :

 
Sélectionnez
zf create project tutoriel-zf

L'outil du ZF créera un dossier nommé tutoriel-zf et le remplira avec la structure de répertoires conseillée. Cette structure suppose que vous ayez le contrôle complet de la configuration d'Apache, de façon à pouvoir laisser la majorité des fichiers en dehors du répertoire web racine.

Image non disponible

(il y a aussi un fichier .htaccess dans public/)

Le répertoire Application/ est l'emplacement où réside le code source pour ce site. Comme vous pouvez le constater, nous avons des répertoires séparés pour les fichiers du modèle, de la vue et du contrôleur de notre application. le répertoire public/ est la racine du site web accessible au public, ce qui signifie que l'URL permettant d'obtenir l'application sera http://localhost/tutoriel-zf/public. De cette façon la majorité des fichiers de l'application ne sont pas directement accessibles par Apache et sont donc plus sécurisés.

Sur un site de production, vous devriez créer un hôte virtuel pour le site web et définir la racine du site directement au répertoire public. Par exemple vous pourriez créer un hôte virtuel appelé tutoriel.zf.localhost qui ressemblerait à ça :

 
Sélectionnez

					<VirtualHost *:80>
						ServerName tutoriel.zf.localhost
						DocumentRoot /var/www/html/tutoriel-zf/public
						<Directory "/var/www/html/tutoriel-zf/public">
							AllowOverride All
						</Directory>
					</VirtualHost>
					

Le site serait alors accessible en utilisant http://tutoriel.zf.localhost/ (assurez-vous d'avoir mis à jour votre fichier /etc/hosts ou C:\Windows\system32\drivers\etc\hosts de façon à rediriger tutoriel.zf.localhost vers 127.0.0.1). Nous ne le ferons pas dans ce tutoriel car il est aussi simple d'utiliser un sous-répertoire pour tester.

Les fichiers images, JavaScript et CSS indépendants seront stockés dans des répertoires séparés dans le dossier public/. Les fichiers téléchargés du Zend Framework seront placés dans le répertoire library/. Si nous avons besoin d'utiliser d'autres bibliothèques, nous pourrons aussi les placer à cet endroit.

Copiez le répertoire library/Zend/ du fichier archive téléchargé (ZendFramework-1.9.0.zip) dans votre tutoriel-zf/library/, de telle sorte que votre tutoriel-zf/library/ contienne un sous-répertoire appelé Zend/.

Vous pouvez tester que tout est correct en allant sur http://localhost/tutoriel-zf/public. Vous devriez voir quelque chose comme ça :

Image non disponible

V-B. Bootstrapping en tâche de fond

Le contôleur du Zend Framework utilise le patron de conception Front Controller et route toutes les requêtes vers un unique fichier index.php. Cela assure de correctement définir l'environnement pour exécuter l'application (connu sous le terme de bootstraping). Nous y parvenons en utilisant un fichier .htaccess dans le répertoire tutoriel-zf/public, généré pour nous par Zend_Tool, qui redirige toutes les requêtes vers public/index.php, également créé par Zend_Tool.

Le fichier index.php est le point d'entrée de notre application et est utilisé pour créer une instance de Zend_Application pour initialiser notre application et enfin la lancer. Ce fichier définit aussi deux constantes : APPLICATION_PATH et APPLICATION_ENV qui définissent le chemin vers le répertoire application/ et l'environnement ou le mode de l'application. Le fichier .htaccess généré l'initialise à development.

Le composant Zend_Application est utilisé pour démarrer l'application et est configuré pour utiliser les directives du fichier de configuration application/configs/application.ini. Ce ficier est aussi auto-généré pour nous. Une classe Bootstrap qui hérite de Zend_Application_Bootstrap_Bootstrap est fournie dans application/Bootstrap.php et peut être utilisée pour exécuter tout code requis au démarrage.

V-C. Editer le fichier application.ini

Bien que Zend_Tool fournisse un fichier de configuration par défaut décent, nous avons besoin d'ajouter nos directives spécifiques à l'application. Modifiez application/configs/application.ini et ajoutez :

 
Sélectionnez
phpSettings.date.timezone = "Europe/Paris"

après toutes les autres valeurs phpSettings de la section [production]. Bien sûr, vous devriez probablement utiliser votre propre fuseau horaire.

V-D. Ajouter l'auto-chargement

Nous avons aussi besoin de créer un auto-chargement des classes qui nous permettra d'automatiquement charger des ressources dans le répertoire application comme les modèles et les formulaires. La classe Zend_Application_Module_Autoloader est utilisée pour le faire et nous l'implémentons dans la classe Bootstrap :

application/Bootstrap.php
Sélectionnez
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
	protected function _initAutoload()
	{
		$moduleLoader = new Zend_Application_Module_Autoloader(array(
			'namespace' => '',
			'basePath' => APPLICATION_PATH));
		return $moduleLoader;
	}
}

Comme cette méthode commence par _init, elle est appelée automatiquement par Zend_Application. Le reste du nom de méthode peut être choisi comme bon vous semble. Le Module_Autoloader chargera les classes avec un certain préfixe qui sont dans certains répertoires situés dans application/ comme dans ce tableau :

Répertoire Préfixe Exemple
api Api_ Api_Rest
forms Form_ Form_Login
models Model_ Model_News
models/DbTable Model_DbTable_ Model_DbTable_News
plugins Plugin_ Plugin_

Nous sommes maintenant prêts à ajouter notre code spécifique à l'application.

VI. Le code spécifique de l'application

Avant de mettre en place nos fichiers, il est important de comprendre l'organisation des pages qu'attend le Zend Framework. Chaque page de l'application est connue comme une action et les actions sont regroupées dans des contrôleurs (controllers). Avec une URL au format http://localhost/public/tutoriel-zf/actuatlites/voir, le contrôleur est Actualites et l'action est voir.Cela permet de regrouper des actions apparentées. Par exemple, un contrôleur Actualites peut avoir les actions lister, archives et voir. Le système MVC du Zend Framework supporte aussi les modules pour regrouper les contrôleurs ensemble, mais cette application n'est pas suffisamment importante pour s'en préoccuper.

Le contrôleur du Zend Framework utilise une action spéciale appelée index comme action par défaut. C'est pour des cas comme http://localhost/tutoriel-zf/public/actualites/ pour lequel l'action index du contrôleur Actualites sera exécutée. Il y a aussi un contrôleur par défaut, ce qui permet de ne pas en indiquer : aucune surprise qu'il soit également appelé index. Ainsi, l'URL http://localhost/tutoriel-zf/public/ exécutera l'action index du contrôleur index.

Comme c'est un tutoriel simple, nous ne nous occuperons pas de choses "complexes" comme se connecter ! Cela attendra un tutoriel différent (ou vous pouvez en lire plus dans Zend Framework in Action !).

Puisque nous avons quatre pages, toutes s'appliquant aux albums, nous allons les regrouper en un seul contrôleur avec quatre actions. Nous utiliserons le contrôleur par défaut et les actions seront :

Page Contrôleur Action
Accueil Index index
Ajouter un album Index ajouter
Modifier un album Index modifier
Supprimer un album Index supprimer

Au fur et à mesure qu'un site se complexifie, des contrôleurs supplémentaires sont nécessaires et vous pouvez même si besoin en grouper plusieurs dans des modules.

VII. Mettre en place le contrôleur

Nous sommes maintenant prêts à mettre en place le contrôleur. Avec Zend Framework, le contrôleur est une classe qui doit être appelée {Nom du contrôleur}Controller.

{Nom du contrôleur} doit commencer par une lettre majuscule.

Cette classe doit être dans un script appelé {Nom du contrôleur}Controller.php dans le répertoire application/controllers. Chaque action est une fonction publique dans le contrôleur et doit être appelée {nom de l'action}Action. Dans ce cas, {nom de l'action} doit commencer par une lettre minuscule et de nouveau être complètement en minuscules. Les noms d'action et de contrôleur contenant des majuscules sont permis, mais il existe des règles spéciales que vous devez comprendre avant de les utiliser. Commencez par vérifier dans la documentation !

Notre classe contrôleur s'appelle IndexController, est définie dans application/controllers/IndexController.php et a été automatiquement créée par nous par Zend_Tool. Nous avons juste besoin d'ajouter nos actions supplémentaires.

Ajouter des actions supplémentaires se fait en utilisant l'outil en ligne de commandes zf. Ouvrez un terminal ou une invite de commandes et placez vous dans votre répertoire tutoriel-zf/. Tapez ensuite ces trois commandes :

  • zf create action ajouter index
  • zf create action modifier index
  • zf create action supprimer index

Ces commandes créent les fonctions xxxAction dans IndexController et créent aussi les fichiers de script de vue appropriés dont nous aurons besoin plus tard. Nous avons maintenant mis en place les quatre actions que nous voulons utiliser.

Les URLs de chaque action sont :

URL Méthode d'action
http://localhost/tutoriel-zf/public/ IndexController::indexAction()
http://localhost/tutoriel-zf/public/index/ajouter IndexController::ajouterAction()
http://localhost/tutoriel-zf/public/index/modifier IndexController::modifierAction()
http://localhost/tutoriel-zf/public/index/supprimer IndexController::supprimerAction()

Vous pouvez les tester, et devriez voir un message comme celui-ci :

Image non disponible

Il est temps de regarder la base de données.

VIII. La base de données

Maintenant que nous avons le squelette de l'application avec les méthodes d'action du contrôleur et les fichiers de vue prêts, il est temps de regarder le modèle de notre application. Rappelez-vous que le modèle est la partie qui s'occupe de l'objectif central de l'application (communément appelé la logique applicative) et, dans notre cas, s'occupe de la base de données. Nous nous servirons de la classe du Zend Framework Zend_Db_Table qui est utilisée pour trouver, ajouter, modifier ou supprimer des enregistrements de la base de données.

VIII-A. Configuration de la base de données

Pour utiliser Zend_Db_Table, nous avons besoin de lui indiquer quelle base de données utiliser, avec un utilisateur et un mot de passe. Puisque nous préférons ne pas coder en dur ces informations dans l'application, nous allons utiliser un fichier de configuration pour les gérer. Le composant Zend_Application est fourni avec une resource de configuration de base de données, nous avons donc juste besoin de définir les informations appropriées dans le fichier configs/application.ini et il s'occupera du reste.

Ouvrez configs/application.ini et ajoutez ce qui suit à la fin de la section [production] (i.e. avant la section [staging]) :

 
Sélectionnez
resources.db.adapter = PDO_MYSQL
resources.db.params.host = localhost
resources.db.params.username = rob
resources.db.params.password = 123456
resources.db.params.dbname = tutoriel-zf

Vous devez évidemment utiliser votre nom d'utilisateur, votre mot de passe et votre nom de base de données, pas les miens ! La connexion à la base de données sera maintenant établie pour nous et l'adaptateur par défaut pour Zend_Db_Table sera défini.

VIII-B. Création de la table

J'utiliserai MySQL et donc la requête SQL pour créer la table est la suivante :

 
Sélectionnez
CREATE TABLE albums (
    id int(11) NOT NULL auto_increment,
    artiste varchar(100) NOT NULL,
    titre varchar(100) NOT NULL,
    PRIMARY KEY (id)
);

Exécutez cette requête avec un client MySQL comme phpMyAdmin ou le client MySQL standard en lignes de commandes.

VIII-C. Insertion d'albums de test

Nous allons également ajouter quelques enregistrements dans la table de manière à pouvoir tester la fonctionnalité de récupération de la page d'accueil. Je vais prendre quelques CDs "meilleures ventes" à partir d'Amazon UK. Exécutez la requête suivante dans votre client MySQL :

 
Sélectionnez
INSERT INTO albums (artiste, titre)
VALUES
('Bob Dylan', 'Together Through Life'),
('Various Artists', 'Now That\'s what I Call Music! 72'),
('Lady Gaga', 'The Fame'),
('Lily Allen', 'It\'s Not Me, It\'s You'),
('Kings of Leon', 'Only By The Night');

Nous avons maintenant quelques données dans la base et pouvons écrire un modèle très simple pour elles.

IX. Le modèle

Le Zend Framework fournit Zend_Db_Table qui implémente le patron de conception Table Data Gateway pour permettre de s'interfacer avec les données d'une table de base de données. Pour des projets plus compliqués, ça vaut généralement la peine de créer une classe modèle qui utilise une ou plusieurs instances de Zend_Db_Table à travers des variables membres protégées. Toutefois, pour ce tutoriel, nous allons créer un modèle qui étend Zend_Db_Table.

Zend_Db_Table est une classe abstraite, nous devons donc en hériter pour définir notre classe spécifique à la gestion des albums. Peu importe le nom de notre classe, mais il est logique de lui donner le nom de la table de la base de données. En ajoutant le préfixe, notre classe s'appelle Model_DbTable_Albums puisque notre nom de table est "albums". Pour indiquer à Zend_Db_Table le nom de la table qu'il devra gérer, nous devons remplir la propriété protégée $_name avec le nom de la table. De plus, Zend_Db_Table suppose que votre table a une clef primaire appelée id qui est auto-incrementée par la base de données. Le nom de ce champ peut être également modifié si besoin est.

Nous stockerons la classe Albums dans un fichier appelé Albums.php dans le répertoire applications/models/DbTable. Créez ce fichier et entrez le code suivant :

tutoriel-zf/application/models/DbTable/Albums.php
Sélectionnez
<?php

class Model_DbTable_Albums extends Zend_Db_Table_Abstract
{
    protected $_name = 'albums';

    public function obtenirAlbum($id)
    {
        $id = (int)$id;
        $row = $this->fetchRow('id = ' . $id);
        if (!$row) {
            throw new Exception("Count not find row $id");
        }
        return $row->toArray();
    }

    public function ajouterAlbum($artiste, $titre)
    {
        $data = array(
            'artiste' => $artiste,
            'titre' => $titre,
        );
        $this->insert($data);
    }

    public function modifierAlbum($id, $artiste, $titre)
    {
        $data = array(
            'artiste' => $artiste,
            'titre' => $titre,
        );
        $this->update($data, 'id = '. (int)$id);
    }

    public function supprimerAlbum($id)
    {
        $this->delete('id =' . (int)$id);
    }
}

Nous créons quatre méthodes d'aide que notre application utilisera pour s'interfacer avec la table de base de données. getAlbum() récupère un enregistrement unique dans un tableau, addAlbum() crée un nouvel enregistrement dans la base de données, updateAlbum() met à jour un enregistrement d'album et deleteAlbum() supprime complètement l'enregistrement. Le code pour chacune de ces méthodes est explicite. Même si ce n'est pas utile dans ce tutoriel, vous pouvez aussi indiquer à Zend_Db_Table les tables liées et il peut récupérer également les données liées.

Nous devons remplir les contrôleurs avec les données du modèle et demander aux scripts de vue de les afficher. Cependant, avant de le faire, nous devons comprendre le fonctionnement du système de vue du Zend Framework.

X. Mise en page et vues

Le composant de vue du Zend Framework est, sans surprise, appelé Zend_View. Le composant de vue nous permettra de séparer le code qui affiche une page du code des méthodes d'action.

L'utilisation basique de Zend_View est la suivante :

 
Sélectionnez
$view = new Zend_View();
$view->setScriptPath('/path/to/scripts');
echo $view->render('script.php');

Vous voyez très facilement que si nous mettions ce squelette directement dans chacune de nos méthodes d'action nous répéterions du code "structurel" très ennuyeux qui n'a pas d'intérêt pour l'action. Nous devrions plutôt initialiser la vue ailleurs et ensuite accéder à notre objet de vue déjà initialisé dans chaque méthode d'action. Le Zend Framework nous fournit une aide d'action appelée ViewRenderer. Elle prend soin d'initialiser une propriété de vue dans le contrôleur ($this->view) pour que nous l'utilisions et rend également un script de vue après traitement de l'action.

Pour le rendu, le ViewRenderer demande à l'objet Zend_View de rechercher les scripts de vue à rendre dans views/scripts/{nom du contrôleur} et rendra (au moins par défaut) le script nommé comme l'action avec l'extension phtml. Ainsi, le script de vue rendu est views/scripts/{nom du contrôleur}/{nom de l'action}.phtml et les contenus rendus sont ajoutés au corps de l'objet réponse. L'objet réponse est utilisé pour rassembler toutes les en-têtes HTTP, le corps du contenu et les exceptions générées par l'utilisation du système MVC. Le contrôleur frontal envoie automatiquement les en-têtes suivis par le contenu du corps à la fin de la répartition (dispatch).

Tout est mis en place pour nous par Zend_Tool quand nous créons le projet et ajoutons des contrôleurs et des actions en utilisant les commandes zf create controller et zf create action.

X-A. Code HTML en commun : Layouts

Il devient très vite évident que nous aurons beaucoup de code HTML en commun dans nos vues pour les sections d'en-tête et de pied de page, et peut-être aussi une ou deux barres latérales également. C'est un problème très classique, et le composant Zend_Layout est conçu pour y remédier. Zend_Layout nous permet de déplacer tout le code commun des en-têtes, pieds de page et autre vers un script de "mise en page" (layout) qui se charge alors d'inclure le code de vue spécifique de l'action en cours d'exécution.

L'emplacement par défaut pour stocker nos layouts est application/layouts/ et il existe une ressource de Zend_Application qui configurera Zend_Layout pour nous. Tout d'abord, créez le répertoire application/layouts/ et ajoutez cette ligne à la fin de la section [production] du fichier configs/applications.ini.

 
Sélectionnez
resources.layout.layoutpath = APPLICATION_PATH "/layouts"

Nous devons aussi définir les paramètres globaux de notre vue dans la classe Bootstrap. De nouveau, nous utilisons une méthode _init() que nous appelons _initViewHelpers(), donc modifiez application/Bootstrap.php et ajoutez le code suivant sous la méthode _initAutoload() :

application/Bootstrap.php
Sélectionnez
...
protected function _initViewHelpers()
{
    $this->bootstrap('layout');
    $layout = $this->getResource('layout');
    $view = $layout->getView();
    $view->doctype('XHTML1_STRICT');
    $view->headMeta()->appendHttpEquiv('Content-Type', 'text/html;charset=utf-8');
    $view->headTitle()->setSeparator(' - ');
    $view->headTitle(' Tutoriel Zend Framework');
}
...

Nous utilisons la variable membre bootstrap() pour s'assurer que la ressource layout est initialisée, puis nous récupérons l'objet Zend_Layout en utilisant getResource() et la vue avec la méthode getView() du layout.

Une fois que nous avons l'instance $view, nous pouvons appeler différentes méthodes d'aide pour la préparer au rendu ultérieur. L'aide de vue doctype() est utilisée pour définir le doctype que nous voulons. C'est utilisé par d'autres aides de vue pour s'assurer que le bon code HTML est généré. Nous utilisons headMeta() pour définir le tag meta de type de contenu puis l'aide de vue headTitle() définit la dernière partie de l'élément <title> ainsi que le séparateur entre chaque partie.

Lors de la répartition (dispatching), Zend_Layout cherchera maintenant un script de vue de mise en page appelé layout.phml dans le répertoire application/layouts, donc nous ferions mieux d'en écrire un ! Voici le fichier :

tutoriel-zf/application/layouts/layout.phtml
Sélectionnez
<?php echo $this->doctype(); ?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
    <?php echo $this->headMeta(); ?>
    <?php echo $this->headTitle(); ?>
</head>
<body>
    <div id="content">
        <h1><?php echo $this->escape($this->title); ?></h1>
        <?php echo $this->layout()->content; ?>
    </div>
</body>
</html>

Le fichier de mise en page contient le code HTML "externe" qui est tout ce qu'il y a de plus classique. Comme c'est un fichier PHP normal, nous pouvons utiliser du PHP à l'intérieur. Une variable disponible, $this, est une instance de l'objet de vue créé pendant le bootstrapping. Nous pouvons l'utiliser pour récupérer les données affectées à la vue et aussi pour appeler des méthodes. Les méthodes (connues comme des aides de vue) retournent une chaîne de caractères que nous pouvons alors afficher.

Pour commencer, nous utilisons les aides de vue que nous avons paramétrées dans Bootstrap::_initViewHelpers() et qui créent le code adéquat pour la section <head>. Dans le <body>, nous créons une division (div) avec un <h1> contenant le titre. Pour rendre le script de vue de l'action en cours, nous affichons l'emplacement virtuel content en utilisant l'aide de vue layout() : echo $this->layout()->content; qui fait le travail pour nous. Cela implique que les scripts de vue de l'action soient exécutés avant le script de vue de mise en page.

Vous pouvez maintenant tester de nouveau les quatre URLs et ne devriez voir aucune différence depuis la dernière fois ! La différence clé est que cette fois, tout le travail est fait dans le layout.

X-B. Mise en forme

Bien qu'il s'agisse juste d'un tutoriel, nous aurons besoin d'un fichier CSS pour que notre application soit un minimum présentable ! Cela pose un problème mineur, car nous ne savons pas réellement comment référencer le fichier CSS puisque l'URL n'indique pas le bon répertoire racine.

Dans la version 1.9 du Zend Framework, une aide de vue appelée baseUrl() est disponible. Cette aide récupère l'information dont nous avons besoin à partir de l'objet de requête et nous donne la partie de l'URL que nous ne connaissons pas.

Dans la version 1.8 du Zend Framework, l'aide de vue baseUrl() n'est pas fournie, donc nous devons créer la nôtre. Les aides de vue résident dans le sous-répertoire application/views/helpers et sont appelées {Nom de l'aide}.php (la première lettre doit être en majuscules) et il y a une convention de nommage attendue pour la classe contenue ; elle doit être appelée Zend_View_Helper_{Nom de l'aide} (de nouveau, la première lettre est en majuscules). La classe doit avoir une méthode appelée {nom de l'aide}() (première lettre en minuscules cette fois - n'oubliez pas !). Dans notre cas, le fichier s'appelle BaseUrl.php et ressemble à ça :

tutoriel-zf/application/views/helpers/BaseUrl.php
Sélectionnez
<?php

class Zend_View_Helper_BaseUrl
{
    function baseUrl()
    {
        $fc = Zend_Controller_Front::getInstance();
        return $fc->getBaseUrl();
    }
}

Ce n'est pas une méthode complexe. Nous récupérons simplement une instance du contrôleur frontal et nous retournons la valeur de sa méthode getBaseUrl().

Notez que dans ZF 1.8 ou 1.9, si vous voulez créer vos propres aides de vue, alors le procédé est exactement le même que pour créer votre propre aide de vue baseUrl().

Pour continuer, nous devons ajouter le fichier CSS à la section <head> du fichier application/layouts/layout.phtml et nous utilisons de nouveau une aide de vue, headLink() :

tutoriel-zf/application/layouts/layout.phtml
Sélectionnez
...
<head>
    <?php echo $this->HeadMeta(); ?>
    <?php echo $this->headTitle(); ?>
    <?php echo $this->headLink()->prependStylesheet($this->baseUrl().'/css/site.css'); ?>
</head>
...

En utilisant headLink(), nous permettons à des fichiers CSS supplémentaires, plus spécifiques, d'être ajoutés dans les scripts de vue du contrôleur, et ils seront alors ajoutés à la section <head> après site.css.

Pour terminer, nous avons besoin de quelques styles CSS, donc créez un répertoire css dans public/ :

tutoriel-zf/public/css/site.css
Sélectionnez
body,html {
    margin: 0 5px;
    font-family: Verdana,sans-serif;
}

h1 {
    font-size: 1.4em;
    color: #008000;
}

a {
    color: #008000;
}

/* Table */
th {
    text-align: left;
}

td, th {
    padding-right: 5px;
}

/* style form */
form dt {
    width: 100px;
    display: block;
    float: left;
    clear: left;
}

form dd {
    margin-left: 0;
    float: left;
}

form #submitbutton {
    margin-left: 100px;
}

Cela devrait le rendre un peu plus joli, mais comme vous le remarquez, je ne suis pas un designer !

Nous pouvons maintenant nettoyer les quatre scripts d'action qui ont été auto-générés pour nous prêts à être remplis, donc allez-y et videz les fichiers index.phtml, ajouter.phtml, modifier.phtml et supprimer.phtml qui, comme vous vous souvenez sans doute, sont dans le répertoire application/views/scripts/index.

XI. Lister les albums

Maintenant que nous avons mis en place la configuration, les informations de la base de données et nos squelettes de vues, nous pouvons entrer dans le vif du sujet et afficher quelques albums. C'est fait dans la classe IndexController et nous commençons par lister les albums de la table dans la méthode indexAction() :

tutoriel-zf/application/controllers/IndexController.php
Sélectionnez
...
function indexAction()
{
    $this->view->title = "Mes Albums";
    $this->view->headTitle($this->view->title, 'PREPEND');
    $albums = new Model_DbTable_Albums();
    $this->view->albums = $albums->fetchAll();
}
...

Nous commençons par définir le titre de la page, puis nous l'ajoutons au headTitle pour l'afficher dans la barre de titre du navigateur.

La méthode fetchAll() retourne un Zend_Db_Table_Rowset qui nous permettra de parcourir les enregistrements retournés dans le script de vue de l'action. Nous pouvons maintenant remplir le script de vue associé, index.phtml.

tutoriel-zf/application/views/scripts/index/index.phtml
Sélectionnez
<p><a href="<?php echo $this->url(array('controller'=>'index',
        'action'=>'ajouter'));?>">Ajouter de nouveaux albums</a></p>
<table>
    <tr>
        <th>Titre</th>
        <th>Artiste</th>
        <th>&nbsp;</th>
    </tr>
<?php foreach($this->albums as $album) : ?>
    <tr>
        <td><?php echo $this->escape($album->titre);?></td>
        <td><?php echo $this->escape($album->artiste);?></td>
        <td>
            <a href="<?php echo $this->url(array('controller'=>'index',
                'action'=>'modifier', 'id'=>$album->id));?>">Modifier</a>
            <a href="<?php echo $this->url(array('controller'=>'index',
                'action'=>'supprimer', 'id'=>$album->id));?>">Supprimer</a>
        </td>
    </tr>
<?php endforeach; ?>
</table>

La première chose que nous faisons est de créer un lien pour ajouter un nouvel album. L'aide de vue url() est fournie par le framework et crée des adresses en utilisant la bonne URL de base. Nous lui passons simplement un tableau des paramètres dont nous avons besoin et elle s'occupe du reste dans la mesure du besoin.

Nous créons ensuite un tableau HTML pour afficher le titre de l'album, l'artiste et des liens permettant de modifier ou de supprimer l'enregistrement. Une boucle classique foreach: est utilisée pour parcourir la liste des albums, et nous utilisons la syntaxe alternative avec deux points et endforeach; car elle est plus simple à lire que d'essayer de faire correspondre des accolades. L'aide de vue url() est là aussi utilisée pour créer les liens de modification et de suppression.

http://localhost/tutoriel-zf/public (ou toute adresse dérivée que vous avez choisie !) devrait maintenant montrer une belle liste d'albums, quelque chose comme ça :

Page d'accueil

XII. Ajouter de nouveaux albums

Nous allons maintenant programmer une fonctionnalité pour ajouter de nouveaux albums.

Il y a deux étapes à cette partie :
  • Afficher un formulaire pour que l'utilisateur fournisse des détails ;
  • Traiter la soumission du formulaire et enregistrer en base de données.

Nous utilisons Zend_Form pour y parvenir. Ce composant nous permet de créer un formulaire et d'en valider la saisie. Nous créons une nouvelle classe Form_Album qui étend Zend_Form pour définir notre formulaire. Comme nous utilisons le module d'auto-chargement, la classe est stockée dans le fichier Album.php dans le répertoire forms :

tutoriel-zf/application/forms/Album.php
Sélectionnez
<?php

class Form_Album extends Zend_Form
{
    public function __construct($options = null)
    {
        parent::__construct($options);
        $this->setName('album');

        $id = new Zend_Form_Element_Hidden('id');

        $artiste = new Zend_Form_Element_Text('artiste');
        $artiste->setLabel('Artiste')
                ->setRequired(true)
                ->addFilter('StripTags')
                ->addFilter('StringTrim')
                ->addValidator('NotEmpty');

        $titre = new Zend_Form_Element_Text('titre');
        $titre->setLabel('Titre')
              ->setRequired(true)
              ->addFilter('StripTags')
              ->addFilter('StringTrim')
              ->addValidator('NotEmpty');

        $envoyer = new Zend_Form_Element_Submit('envoyer');
        $envoyer->setAttrib('id', 'boutonenvoyer');

        $this->addElements(array($id, $artiste, $titre, $envoyer));
    }
}

Dans le constructeur de Form_Album, nous créons quatre éléments pour l'id, l'artiste, le titre et le bouton d'envoi. Chaque élément se voit affecter certains attributs, notamment le libellé à afficher. Pour les éléments textuels, nous ajoutons deux filtres StripTags et StringTrim pour supprimer le HTML non désiré et les espaces inutiles. Nous les rendons également obligatoires et leur ajoutons un validateur NotEmpty (non vide) pour nous assurer que l'utilisateur entre véritablement l'information dont nous avons besoin.

Nous avons maintenant besoin d'afficher le formulaire et d'en récupérer les données. Cela se fait dans l'action ajouterAction() du contrôleur IndexController :

tutoriel-zf/application/controllers/IndexController.php
Sélectionnez
...
function ajouterAction()
{
    $this->view->title = "Ajouter un nouvel album";
    $this->view->headTitle($this->view->title, 'PREPEND');

    $form = new Form_Album();
    $form->envoyer->setLabel('Ajouter');
    $this->view->form = $form;

    if ($this->getRequest()->isPost()) {
        $formData = $this->getRequest()->getPost();
        if ($form->isValid($formData)) {
            $artiste = $form->getValue('artiste');
            $titre = $form->getValue('titre');
            $albums = new Model_DbTable_Albums();
            $albums->ajouterAlbum($artiste, $titre);

            $this->_redirect('/');
        } else {
            $form->populate($formData);
        }
    }
}
...

Examinons ça plus en détails :

 
Sélectionnez
    $form = new Form_Album();
    $form->envoyer->setLabel('Ajouter');
    $this->view->form = $form;

Nous instancions notre Form_Album, nous affectons au bouton d'envoi le libellé "Ajouter" puis nous assignons le formulaire à la vue pour affichage.

 
Sélectionnez
    if ($this->getRequest()->isPost()) {
        $formData = $this->getRequest()->getPost();
        if ($form->isValid($formData)) {

Si la méthode isPost() de l'objet de requête renvoie true, alors le formulaire a été envoyé. Nous récupérons les données de la requête avec la méthode getPost() et nous vérifions qu'elles sont valides avec la méthode membre isValid().

 
Sélectionnez
            $artiste = $form->getValue('artiste');
            $titre = $form->getValue('titre');
            $albums = new Model_DbTable_Albums();
            $albums->ajouterAlbum($artiste, $titre);

Si le formulaire est valide, nous instancions la classe modèle Model_DbTable_Albums et nous utilisons la méthode ajouterAlbum() que nous avons créée plus tôt pour créer un nouvel enregistrement dans la base de données.

 
Sélectionnez
            $this->_redirect('/');

Après avoir sauvegardé le nouvel enregistrement d'album, nous redirigeons vers la page d'accueil avec la méthode _redirect() du contrôleur.

 
Sélectionnez
        } else {
            $form->populate($formData);
        }

Si les données du formulaire ne sont pas valides, nous le remplissons avec les données fournies et nous l'affichons à nouveau (4).

Nous avons maintenant besoin d'afficher le formuaire dans le script de vue ajouter.phtml :

tutoriel-zf/application/views/scripts/index/ajouter.phtml
Sélectionnez
<?php echo $this->form ;?>

Comme vous pouvez le constater, afficher un formulaire est très simple puisqu'il sait comment se prendre en charge.

XIII. Modifier un album

Modifier un album est presque identique à en ajouter un, le code est donc vraiment similaire :

tutoriel-zf/application/controllers/IndexController.php
Sélectionnez
...
function modifierAction()
{
    $this->view->title = "Modifier l'album";
    $this->view->headTitle($this->view->title, 'PREPEND');

    $form = new Form_Album();
    $form->envoyer->setLabel('Sauvegarder');
    $this->view->form = $form;

    if ($this->getRequest()->isPost()) {
        $formData = $this->getRequest()->getPost();
        if ($form->isValid($formData)) {
            $id = (int)$form->getValue('id');
            $artiste = $form->getValue('artiste');
            $titre = $form->getValue('titre');
            $albums = new Model_DbTable_Albums();
            $albums->modifierAlbum($id, $artiste, $titre);

            $this->_redirect('/');
        } else {
            $form->populate($formData);
        }
    } else {
        $id = $this->_getParam('id', 0);
        if ($id > 0) {
            $albums = new Model_DbTable_Albums();
            $form->populate($albums->obtenirAlbum($id));
        }
    }
}
...

Regardons les différences avec l'ajout d'un album. Premièrement, lorsque nous affichons le formulaire, nous devons récupérer l'artiste et le titre de l'album à partir de la base de données puis renseigner les éléments du formulaire avec. C'est à la fin de la méthode :

 
Sélectionnez
        $id = $this->_getParam('id', 0);
        if ($id > 0) {
            $albums = new Model_DbTable_Albums();
            $form->populate($albums->obtenirAlbum($id));
        }

Ce n'est exécuté que si la requête n'est pas de type POST. Nous récupérons l'id de la requête en utilisant la méthode _getParam(). Nous utilisons ensuite le modèle pour récupérer l'enregistrement de la base de données et remplir le formulaire directement avec les données de l'enregistrement.

Après validation du formulaire, nous devons sauvegarder les données sur le bon enregistrement de base de données. C'est fait en utilisant notre méthode modifierAlbum() du modèle :

 
Sélectionnez
            $id = (int)$form->getValue('id');
            $artiste = $form->getValue('artiste');
            $titre = $form->getValue('titre');
            $albums = new Model_DbTable_Albums();
            $albums->modifierAlbum($id, $artiste, $titre);

Le script de vue est le même qu'ajouter.phtml :

tutoriel-zf/application/views/scripts/index/modifier.phtml
Sélectionnez
<?php echo $this->form ;?>

Vous devriez désormais être en mesure d'ajouter et de modifier des albums.

XIV. Supprimer un album

Pour terminer notre application, nous devons ajouter la suppression. Nous avons un lien "supprimer" à côté de chaque album de notre liste et l'approche naïve serait de supprimer un album lorsque le lien est utilisé. Ce serait une erreur. Souvenez-vous de nos spécifications HTTP : nous vous rappelons que vous ne devriez pas faire d'action irréversible en utilisant une requête GET mais plutôt POST.

Nous devons afficher un formulaire de confirmation quand l'utilisateur clique sur supprimer et, s'il clique sur "Oui", nous effectuerons la suppression. Puisque ce formulaire est trivial, nous le coderons directement dans notre vue.

Commençons par le code de l'action dans IndexController::supprimerAction() :

tutoriel-zf/application/controllers/IndexController.php
Sélectionnez
...
public function supprimerAction()
{
    $this->view->title = "Supprimer l'album";
    $this->view->headTitle($this->view->title, 'PREPEND');

    if ($this->getRequest()->isPost()) {
        $supprimer = $this->getRequest()->getPost('supprimer');
        if ($supprimer == 'Oui') {
            $id = $this->getRequest()->getPost('id');
            $albums = new Model_DbTable_Albums();
            $albums->supprimerAlbum($id);
        }

        $this->_redirect('/');
    } else {
        $id = $this->_getParam('id', 0);
        $albums = new Model_DbTable_Albums();
        $this->view->album = $albums->obtenirAlbum($id);
    }
}
...

Comme pour l'ajout et la modification, nous utilisons la méthode isPost() de la requête pour savoir si nous devons afficher le formulaire ou bien effectuer la suppression. Nous utilisons Model_DbTable_Albums pour réellement supprimer l'enregistrement en utilisant la méthode supprimerAlbum(). Si la requête n'est pas de type POST, alors nous recherchons un paramètre "id", récupérons le bon enregistrement de base de données et l'assignons la vue.

Le script de vue est un simple formulaire :

tutoriel-zf/application/views/scripts/index/supprimer.phtml
Sélectionnez
<p>Êtes-vous sûr de vouloir supprimer 
    '<?php echo $this->escape($this->album['titre']); ?>' de
    '<?php echo $this->escape($this->album['artiste']); ?>'?
</p>
<form action="<?php echo $this->url(array('action'=>'supprimer')); ?>" method="post">
<div>
    <input type="hidden" name="id" value="<?php echo $this->album['id']; ?>" />
    <input type="submit" name="supprimer" value="Oui" />
    <input type="submit" name="supprimer" value="Non" />
</div>
</form>

Dans ce script, nous présentons un message de confirmation à l'utilisateur ainsi qu'un formulaire avec les boutons "Oui" et "Non". Dans l'action, nous avons vérifié spécifiquement la valeur "Oui" avant la suppresion.

C'est tout. Vous avez maintenant une application pleinement fonctionnelle.

XV. Conclusion

Cela conclut notre rapide coup d'oeil à la création d'une application MVC simple, mais parfaitement fonctionnelle, avec le Zend Framework. J'espère que vous l'avez trouvé intéressant et instructif. Si vous trouvez une erreur, veuillez m'envoyer un e-mail à !

Ce tutoriel a mis l'accent sur les bases d'utilisation du framework ; il y a beaucoup plus de composants à explorer ! Vous devriez également lire le manuel ! Si vous être intéressé par le développement du framework, alors lisez également le wiki du développement...

Pour terminer, si vous préférez les pages imprimées, j'ai écris un livre appelé Zend Framework in Action qui est disponible. Plus de détails sont disponibles sur http://www.zendframeworkinaction.com. Jetez-y un oeil :-)

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


NdT : Pour plus d'informations sur Zend_Tool, vous pouvez vous référer au tutoriel Créer une application basée sur Zend Framework avec Zend_Tool.
NdT : Ce bug de Zend_Tool est en fait corrigé à partir de la version 1.9.2 du framework.
NdT : Le fichier php.exe doit également être dans le path de Windows, et le répertoire library du framework dans l'include_path de PHP.
NdT : Cette étape est inutile avec les versions récentes du Zend Framework qui remplit automatiquement le formulaire lors de l'utilisation de sa méthode isValid().

  

Copyright © . 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.