Zend Framework : Premiers pas avec Zend_Application
Date de publication : 18 juillet 2009
Par
AIT YAHIA Iidir (Mon site perso) (Blog)
Avec l'avènement de la version 1.8 de Zend_Framework, la configuration du bootstraping peut paraitre à première vue déroutante pour les novices et même pour les confirmés qui ont l'habitude de travailler avec les versions précédentes du Framework. Dans ce tutoriel nous allons essayer de vous montrer comment configurer une application en MVC Avec Zend_Application. Vous allez voir que c'est claire et plus simple que ce que nous faisions d'habitude.
I. Introduction
I-A. Pré-requis
I-B. Présentation
I-C. Pourquoi utiliser Zend_Application ?
II. Mise en œuvre d'une application basique
II-A. Création de la structure de votre application
II-B. Configuration de notre application
II-B-1. Fichier de configuration
II-B-2. Index.php
II-B-3. Fichier .htaccess
II-B-4. Bootstrap
III. Mise en œuvre d'une application modulaire
III-A. Fichier de configuration
III-B. Bootstrap
III-C. les Controlleurs d'actions
IV. Ajouter une ressource
V. Conclusion
I. Introduction
I-A. Pré-requis
Cet article vise un publique ayant de très bonnes connaissances en PHP, le concept MVC et ayant déjà utilisé Zend Framework auparavant.
Ce tutoriel a été réalisé avec la version 1.8.4 du Framework et ne fonctionnera avec aucune des versions antérieures à la version 1.8.
I-B. Présentation
Zend_ Application est l'un des nouveaux composants introduit dans la version 1.8 de Zend Framework, il nous permet de faciliter et de standardiser la mise en place du bootstraping ainsi que la configuration de l'environnement PHP.
Avec Zend_Application l'autoloading est mis de l'avant et le bootstrap se présente sous une forme modulaire ou sont initialisées toutes les ressources réutilisables telles que les vues, les connexions aux bases de données, les layout...etc.
I-C. Pourquoi utiliser Zend_Application ?
Une application MVC peut très rapidement devenir complexe et faire intervenir énormément d'objets, chacun est configurable d'une manière qui lui est propre, chacun est dépendant éventuellement d'autres objets .... Un casse tête est alors apparu : comment créer, configurer, lier et mémoriser tous ces objets de manière pérenne, et propre ?
Zend_Application répond à ces problématiques en proposant une manière simple et efficace de configurer tout l'environnement MVC
II. Mise en œuvre d'une application basique
II-A. Création de la structure de votre application
Pour commencer nous devrions créer une nouvelle application Zend Framework avec la structure conventionnelle semblable à celle présenté dans l'image ci-dessous. Nous pouvons faire cela manuellement, mais il est plus judicieux d'utiliser Zend_Tool qui va faire le plus gros du travail à votre place.
Pour de plus amples détails sur la création d'applications avec Zend_Tool vous pouvez consulter cet article.
Créer une application basée sur Zend Framework avec Zend_Tool
Le dossier public contient aussi le fichier htaccess qui n'apparait pas dans l'arborescence.
II-B. Configuration de notre application
Nous allons maintenant nous intéresser aux fichiers importants pour notre configuration.
II-B-1. Fichier de configuration
Le fichier auquel nous devons accorder une attention et particulière est sans doute notre fichier de configuration application.ini, c'est dans ce fichier que seront initialisés toutes les ressources et l'environnement PHP.
Remarque que vous avons plusieurs sections dans notre application.ini, celles-ci nous permettent d'avoir des configurations distinctes pour chaque mode d'exécution de notre application (production, développement, test...etc.).
application/configs/application.ini |
[ production ]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
phpsettings.date.timezone = "Africa/Algiers"
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.layout.layout = "layout"
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.view.encoding = "UTF-8 "
resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "aityahia"
resources.db.params.password = "monpasse"
resources.db.params.dbname = "zf-zaProject"
resources.db.isDefaultTableAdapter = true
[ staging : production ]
[ testing : production ]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
[ development : production ]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.db.params.dbname = "zf-zaProject-test"
|
Remarque que vous avons plusieurs sections dans notre
application.ini, celles-ci nous permettent d'avoir des configurations distinctes pour chaque mode d'exécution de notre application (production, développement, test...etc.).
Dans notre fichier de configuration, tout ce qui vient après le mot ressources est considéré en tant que telle.
L'option phpSettings nous permet de définir les directives du
php.ini Lorsque cette option est définie Zend_Application fait appel à la fonction php
ini_set , la liste de toutes les directives définissables est disponible sur le site officiel de php
Liste des directives du php.ini
La définition des directives se fait de la manière suivante :
phpSettings.nom_directive = valeur
|
Comme vous pouvez le voir nous avons pratiquement tout initialisé dans notre fichier de configuration, nous avons même défini une base de données spécifique pour les essais en cours de développement.
|
Il nous est tout à fait possible d'utiliser un autre format de fichier de configuration .xml, .inc, .php des exemples sont disponibles dans la documentation officiel. La piste du fichier XML est à écarter si vous utilisez dans votre configuration des constantes définies avec la méthode define (comme c'est dans notre cas avec la constante APPLICATION_PATH), pour cause, Zend_Application utilise en interne Zend_Config_Xml pour la lecture du XML, hors que celui-ci ne prend pas en charge la lecture des constantes d'environnement. Ce problème est valable du moins pour le moment car d'après mes lectures cette restriction sera levée dans la version 1.9 du Framework.
|
II-B-2. Index.php
Dans le fichier index.php nous allons définir les chemins et les constantes d'exécutions dont nous avons besoin, invoquer Zend_Application et en dérnier lieu nous lançons l'application.
Analysons du plus près l'instanciation de Zend_Application
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . ' /configs/application.ini '
);
$application ->bootstrap ()
- > run();
|
Dans cette partie de code nous invoquons Zend_Application en lui indiquant qu'il doit tenir compte de la configuration présente dans notre fichier de configuration, mais il vous est tout à fait possible de lui passer en paramètre un tableau définissant les options de configuration, comme on peut le voir dans cet l'exemple.
$application = new Zend_Application(APPLICATION_ENV, array (
' pluginPaths ' = > array (
' Application_Resources ' = > APPLICATION_PATH . ' /resources/ ' ,
),
' resources ' = > array (
' FrontController ' = > array (
' controllerDirectory ' = > APPLICATION_PATH . ' /controllers ' ,
),
),
));
|
Il est fortement recommandé d'utilisé le fichier de configuration pour ne pas d'encombrer l'instanciation de votre application qui risque de devenir incompréhensible.
Il est à noter que dans les deux cas Zend_Application récupère la configuration sous forme de tableau (Zend_Config_Ini est utilisé en interne pour la lecture de votre fichier configuration).
II-B-3. Fichier .htaccess
Notons bien que nous avons fait appel à la variable d'environnement APPLICATION_ENV, celle-ci peut être définie dans notre fichier htaccess ou dans la configuration apache, c'est elle qui défini le mode d'exécution de votre application.
public/.htaccess |
SetEnv APPLICATION_ENV development
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
|
II-B-4. Bootstrap
Dans notre Bootstrap nous allons initialiser la vue de notre Layout, dans cet exemple nous avons utilisé Zend_View pour sa définition, mais il nous est possible de nous en passer.
Nous allons aussi initialiser notre adaptateur de base de données qui sera utilisable dans tous nos modèles et contrôleurs
application/bootstrap.php |
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap {
protected function _initAutoload() {
$moduleLoader = new Zend_Application_Module_Autoloader (
array (' namespace ' = > ' ' , ' basePath ' = > APPLICATION_PATH ) );
return $ moduleLoader ;
}
protected function _initView() {
$view = new Zend_View ( );
$view ->doctype ( ' XHTML1_STRICT ' );
$view ->headTitle ( ' Mon application avec Zend_Application ' );
$ viewRenderer = Zend_Controller_Action_HelperBroker: : getStaticHelper ( ' ViewRenderer ' );
$viewRenderer ->setView ( $ view );
return $ view ;
}
protected function _initDb() {
$ db = $this ->getPluginResource ( ' db ' )- > getDbAdapter ();
$db ->setFetchMode ( Zend_Db: : FETCH_OBJ );
Zend_Db_Table_Abstract: : setDefaultAdapter ( $ db );
return $ db ;
}
}
|
soit notre fichier layout.phtml
application/layouts/scripts/layout.phtml |
<?php echo $this ->doctype () ?>
< html >
< head >
<?php
echo $this ->headTitle ();
echo $this ->headLink ();
echo $this ->headStyle ();
echo $this ->headScript ();
?>
< / head >
< body >
<?php echo $this ->layout ()- > content ?>
< / body >
< / html >
|
Nous avons terminé avec la configuration de notre application et elle est dès à présent fonctionelle et nous pouvons nous attaquer au développement de nos contrôleurs,modèles et vues...etc.
III. Mise en œuvre d'une application modulaire
Pour la mise en œuvre d'une application modulaire, la configuration se corse un petit peu, mais soyez sans crainte pas au point de vous étourdir, c'est pour cet effet que nous allons étudier ce cas en particulier.
En premier lieu, nous allons remanier notre structure en ajoutant deux modules (default et admin). Dans notre exemple le Layout et les modèles sont commun à nos modules, notre nouvelle structure devra ressembler à ceci.
III-A. Fichier de configuration
Pour notre fichier de configuration, nous allons apporter quelques modifications au contrôleur frontal (Front Controller).
resources.frontController.baseUrl = "/zf-zaProject/public"
resources.frontController.controllerDirectory.default = APPLICATION_PATH "/modules/default/controllers"
resources.frontController.controllerDirectory.admin = APPLICATION_PATH "/modules/admin/controllers"
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.defaultModule = "default"
resources.modules = ""
|
Après modification notre fichier de configuration tel qu'il devrait être.
application/configs/application.ini |
[ production ]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
phpsettings.date.timezone = "Africa/Algiers"
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.baseUrl = "/zf-zaProject/public"
resources.frontController.controllerDirectory.default = APPLICATION_PATH "/modules/default/controllers"
resources.frontController.controllerDirectory.admin = APPLICATION_PATH "/modules/admin/controllers"
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.defaultModule = "default"
resources.modules = ""
resources.layout.layout = "layout"
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.view.encoding = "UTF-8 "
resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "aityahia"
resources.db.params.password = "monpasse"
resources.db.params.dbname = "zf-zaProject"
resources.db.isDefaultTableAdapter = true
[ staging : production ]
[ testing : production ]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
[ development : production ]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.db.params.dbname = "zf-zaProject-test"
|
III-B. Bootstrap
Le Bootstrap de notre application reste inchangé par contre nous devrons définir les classes des Bootstrap de nos modules, celles-ci étendent la classe Zend_Application_Module_Bootstrap, notez bien la différence avec celle de notre application qui étend Zend_Application_Bootstrap_Bootstrap.
application/modules/default/bootstrap.php |
class Bootstrap extends Zend_Application_Module_Bootstrap{
}
|
A l'exception de la classe Bootstrap du module par défaut toutes les autres devront respecter une certaine règle de nommage (Nommodule_ Bootstrap) dans notre cas Admin_Bootstrap. Cette règle peut être appliquée sans effet de la classe Bootstrap du module par défaut.
application/modules/admin/bootstrap.php |
class Admin_Bootstrap extends Zend_Application_Module_Bootstrap {
}
|
|
Il peut paraitre évident, que si nous initialisons une ressource au niveau du Bootstrap de l'un de nos modules, celle-ci est faite uniquement quand le module en question est invoqué; Détrompé vous car ce n'est pas le cas, les méthodes et plugins y afférent sont exécuté bien avant que le contrôleur frontal n'expédie la requête.
|
III-C. les Controlleurs d'actions
Pour pouvoir tester que notre application modulaire fonctionne, nous allons définir les Contrôleurs d'actions index de nos modules.
application/modules/default/IndexController.php |
class IndexController extends Zend_Controller_Action
{
public function init ()
{
$this ->view ->headTitle ( ' Mon application avec Zend_Application (Utilsateur par défaut) ' );
}
public function indexAction()
{
$this ->_response ->appendBody (' Bievenue ' );
}
}
|
Comme pour les classes Bootstrap des modules, les contrôleurs d'actions obéissent à la même règle de nommage. Dans notre exemple Admin_IndexController.
application/modules/admin/IndexController.php |
class Admin_IndexController extends Zend_Controller_Action
{
public function init ()
{
$this ->view ->headTitle ( ' Mon application avec Zend_Application (Administrateur) ' );
}
public function indexAction()
{
$this ->_response ->appendBody (' Bievenue Admin ' );
}
}
|
IV. Ajouter une ressource
Les ressources que nous avons ajoutées jusque-là sont un peu particulières car elles ont des plugins prédéfinis dans Zend_Application et elles répondent à un schéma de configuration bien déterminé. Les ressources dont il est question sont le FrontController, Layout ,Db…etc. Vous pouvez consulter la liste complète avec tous les paramètres de configuration dans la documentation officielle de Zend_Application.
Vous allez vous dire pourquoi ce n'est pas le cas des autres ressources ? Imaginez qu'on avait fait la même chose avec les autres ressources, il serait vraiment très difficile de se souvenir et d'obéir aux différents schémas de configuration vu la quantité innombrable de ressources disponibles donc les concepteurs de Zend Framework nous ont laissés le soin de définir nous même à notre guise la configuration de nos ressources. Rajouter à cela les ressources dont le plugin est préfinit sont considérées comme étant incontournables de l'élaboration dune application MVC.
Si vous avez l'habitude dans le passé d'enregistrer tous les objets, méthodes et ressources que vous initialisés dans votre bootstrap avec Zend_Registry pour leurs réutilisation.
Avec Zend_Application ce n'est plus nécessaire car il fait office de registre est enregistre systématiquement toutes les méthodes et ressources que vous avez définies dans votre bootstrap. Nous allons voir dans les exemples ci-dessous comment il vous possible de les invoquer.
Pour un exemple d'ajout de ressource, nous allons doter notre application d'un Log qui va écrire vers la console de firebug en mode développement et vers un fichier en mode production.
Pour procéder nous allons rajouter deux dossiers (ressources et logs) à la base de notre application, l'un va accueillir les plugins et l'autre notre log.
Nous allons maintenant revenir sur notre fichier application.ini pour initialiser les paramètres de notre log.
application/configs/application.ini |
[ production ]
...
...
...
pluginpaths.Application_Resources = APPLICATION_PATH "/Resources"
resources.logs.writer.type = stream
resources.logs.writer.file = APPLICATION_PATH "/logs/application.log"
...
...
...
[ development : production ]
resources.logs.writer.type = firebug
|
Définissons notre plugin logs.php que nous allons placer dans le dossier que nous avons prévu a cet effet.Lorsque nous ajoutons une ressource à notre fichier de configuration (excepté les ressources préfinis), Zend_Application s'attend toujours à trouver une classe qui étend Zend_Application_Resource_ResourceAbstract dans le dossier plugins dont nous avons définis le path précédemment. La fonction init doit être implicitement déclarée sinon une exception sera déclenchée.
application/resources/logs.php |
class Application_Resources_Logs extends Zend_Application_Resource_ResourceAbstract
{
public function init ()
{
$ options = $this ->getOptions ();
$ type = $ options [ ' writer ' ] [ ' type ' ] ;
switch ( $ type )
{
case ' stream ' :
$writer = new Zend_Log_Writer_Stream($ options [ ' writer ' ] [ ' file ' ] );
break ;
case ' firebug ' :
$writer = new Zend_Log_Writer_Firebug();
break ;
default :
$ writer = NULL ;
}
if (isset($ writer )) {
$logger = new Zend_Log($ writer );
return $ logger ;
}
}
}
|
Ce qui il ya lieu de retenir dans notre logs, est certainement la méthode $this->getOptions() qui récupère les paramètres de notre logs .
- $this fait référence à notre ressource .
- getOptions() récupère les paramètres sous forme d'un tableau, la profondeur d'accès a une option est déterminé par celle définit dans la configuration après le nom de la ressource.
Pour y voir plus claire, si par exemple dans votre fichier de configuration vous avez une ressource définit comme ceci.
resources.nomressource.niveau1.niveau2.niveau3 = test
|
Soit $option est le résultat de la méthode getOptions(), l'option peut être récupérée comme ceci.
$ options [ niveau1] [ niveau2] [ niveau3] = = ' test ' ;
|
Quant il s'agit d'un plugin de ressource la fonction init doit impérativement renvoyer une instance de l'objet, Zend_Log dans notre cas. Pour que Zend_Application l'inscrit dans son registre.
$logger = new Zend_Log($ writer );
return $ logger ;
|
Afin de tester si notre log fonctionne bien nous allons rajouter quelques instructions d'écriture dans nos contrôleurs.
application/modules/default/IndexController.php |
class IndexController extends Zend_Controller_Action
{
public function init ()
{
$this ->view ->headTitle ( ' Mon application avec Zend_Application (Utilsateur par défaut) ' );
}
public function indexAction()
{
$this ->_response ->appendBody (' Bienvenue ' );
$ bootstrap = $this ->getInvokeArg (' bootstrap ' );
if ($bootstrap ->hasResource (' logs ' ))
{
$ logs = $bootstrap ->getResource (' logs ' );
if (isset($ logs )){
$logs ->info (' une information ' );
$logs ->warn (' un avertissement ' );
$logs ->err (' une erreur ' );
}
}
}
}
|
Voici une autre méthode d'accéder à nos ressources, vous pouvez utiliser à votre convenance l'une ou l'autre.
application/modules/admin/IndexController.php |
class Admin_IndexController extends Zend_Controller_Action
{
public function init ()
{
$this ->view ->headTitle ( ' Mon application avec Zend_Application (Administrateur) ' );
}
public function indexAction()
{
$this ->_response ->appendBody (' Bienvenue Admin ' );
$ bootstrap = $this ->getInvokeArg (' bootstrap ' );
$ conteneur = $bootstrap ->getContainer ();
if (isset($conteneur ->logs )) {
$ logs = $ conteneur > logs;
$logs ->info (' une information ' );
$logs ->warn (' un avertissement ' );
$logs ->err (' une erreur ' );
}
}
}
|
V. Conclusion
Personnellement, j'apprécie beaucoup l'utilité de Zend_Application et je trouve que, c'est une très forte valeur ajoutée au Framework, car il apporte une certaine subtilité à la configuration des applications.
Il faut savoir aussi, que nous n'avons évoqué dans ce tutoriel n'est qu'une infime partie de ce qu'on peut faire avec Zend_Application, alors n'hésitez pas à faire un tour dans la documentation officielle pour voir toutes les possibilités que nous offre ce composant.
Zend_Application : Documentation officielle
Les sources présentées sur cette page sont libres de droits
et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation
constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ©
AIT YAHIA Idir. Aucune reproduction, même partielle, ne peut être faite
de ce site ni 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. Droits de diffusion permanents accordés à Developpez LLC.