Support de formation PHP Expert certifié
Transcription
Support de formation PHP Expert certifié
formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Bienvenue Formation ZendFramework architecte 1 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Formation ZF Architecte Votre formateur : Julien Pauli - [email protected] Architecte expert certifié PHP, certifié Zend Framework Membre AFUP - Conférencier – Consultant Co-auteur : ZendFramework, bien développer en PHP Contributeur ZendFramework / PHP / Apache http://julien-pauli.developpez.com http://github.com/jpauli http://twitter.com/julienpauli 2 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Combien d'entre vous ... Utilisent PHP depuis au moins deux ans Ont déjà installé PHP manuellement ? Travaillent sous Linux ? Ont déjà utilisé le ZendFramework, un autre framework? Ont déjà entendu parlé d'UML ? Ont déjà développé en objet (Java, C++, Ruby) ? Ont déjà utilisé des Design Patterns ? Ont déjà développé dans un modèle MVC ? Utilisent des méthodes de dév agiles (XP) – des tests (unitaires...) ? Utilisent des outils de déploiements (Phing) ? ৩ formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Présentations individuelles Quel est votre profil ? Votre nom et votre société Quelle est votre expérience avec PHP ? Pourquoi êtes-vous ici ? Qu'attendez-vous de la formation ? Que voulez-vous apprendre ? ৪ formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Informations pratiques Horaires : 9H30-10h45 Pause 11h00-12h30 Pause déjeuner 13h30-15h15 Pause 15h30-17h00 ৫ formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr ৬ Informations pratiques Il est absolument fondamental de maitriser parfaitement le modèle objet de PHP5 et la manière de concevoir une application objet posez des questions dès que c'est nécessaire Une machine Linux (Debian / Ubuntu) Apache / PHP / MySQL (Paquets ou compilation) PHP Installez PECL (paquet php5-dev et php-pear) Installez APC (installez apache2-prefork-dev avant) Installez un débogueur Xdebug ZendFramework dernière version http://framework.zend.com/download formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr IDE et débogueur Un débogueur est indispensable pour manipuler le ZF en profondeur Nous utiliserons Xdebug Configurez le debuggeur : xdebug.remote_enable=1 xdebug.remote_host=127.0.0.1 Téléchargez l'extension firefox "EasyXdebug" https://addons.mozilla.org/fr/firefox/addon/58688 Nous allons utiliser PDT ou ZendStudio. ৭ formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 8 Formation Zend Framework architecte A: Rappels sur le ZF 1. Les différents packages 2. Le niveau de couplage 3. Les versions et l'évolution du framework 4. Le futur de Zend framework B: Comprendre et maitriser MVC 5. Monter une application MVC 6. Gérer des bases de données 7. Monter un modèle 8. Formulaires, Authentification 9. Application et bootstrap 10. Pattern contrôleur frontal 11. Objets de requête et réponse 12. Routage 13. Vues, templates et Layouts 14. Plugins MVC et aides d'action 15. Aides de vues E: Ajax 16. Introduction à JQuery 17. ZendFramework et Ajax 18. Intégration dans les vues et les layouts F: Gérer la redondance des developpements 19. Génie logiciel, design patterns et UML 20. Couplage, cohésion et responsabilités 21. Utiliser le débogueur pour comprendre le code 22. Créer son propre framework sur ZendFramework G. Testabilité 23. Rappels sur PHPUnit 24. Ecrire et automatiser le lancement des tests 25. Zend_Test et tests fonctionnels 26. Assertions sur le DOM H: Conclusions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Packages Zend Framework? Zend Framework est un framework "glue" Chaque paquet peut être utilisé indépendamment des autres Paquet au sens "package" de Java ou d'UML Sous ensemble logiciel au dessus de la classe Il sera utilisable en PHP5.3 via les namespaces Toute la difficulté réside dans la manière d'assembler ces paquets C'est notre métier Packageizer permet de ne télécharger qu'un (ensemble de) paquets en selectionnant ses dépendances (outil non officiel) http://epic.codeutopia.net/pack/ 9 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Couplage du Zend Framework Installons ext/inclued > pecl config-set preferred_state alpha > pecl install inclued > mkdir /tmp/inclued extension=inclued.so inclued.enabled=1 inclued.dumpdir=/tmp/inclued > apt-get install graphviz > php gengraph.php -i /tmp/inclued.27843.1 Written inclued.out.dot... > dot -Tpng -O inclued.out.dot Installons pear/phpdepends > pear channel-discover pear.pdepend.org > pear install pdepend/PHP_Depend-beta pdepend --summary-xml=/tmp/summary.xml --jdependchart=/tmp/jdepend.svg --overviewpyramid=/tmp/pyramid.svg /path/to/ZF http://manuel-pichler.de/archives/31-Using-the-Overview-Pyramid.html 10 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 11 Versions du Zend Framework La version courante est Zend_Version::VERSION 1.0 (30/06/07) bases 1.5 (24/03/08) Zend_Form, Zend_Layout 1.6 (02/09/08) Dojo, Zend_Soap, Zend_Test, Zend_Paginator, Zend_File_Transfert 1.7 (17/11/08) Zend_Amf, ZendX_JQuery, Zend_Progressbar, Zend_Config_Writer 1.8 (07/04/09) Zend_Tool, Zend_Application, Zend_Reflection, Zend_Loader_Autoloader 1.9 (11/08/09) Support de PHP5.3, Zend_Queue, Zend_Rest_Route, Zend_Feed_Reader, Zend_Test_PHPUnit_Db 1.10 (21/12/09) Zend_Markup, Zend_Feed_Writer, Zend_Cache_Manager, Zend_Barcode 1.11 (2/11/10) Zend_Http_UserAgent, Zend_Cloud, Zend_Service_Ebay, Zend_Service_ShortUrl formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 12 Versions du Zend Framework Majeure.mineure.revision Majeures = compatibilité totalement brisée, changement de l'API Mineures = Compatibilité gardée* , ajout de fonctionnalités (classes, méthodes...) Révisions = Compatibilité gardée, corrections de bugs En mineure, de petites cassures peuvent apparaître Une seule adresse : http://framework.zend.com/changelog La doc officielle indique aussi clairement les mini cassures entre les mineures formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Le futur du Zend Framework ZF 2.0 est sur les rails (10/2011) Utilisation des nouveautés de PHP 5.3 Namespaces, fermetures et fonctions anonymes, méthodes magiques... Support de PHP5.2 abandonné Il faudra migrer vers PHP5.3 Cassure complète de compatibilité La compatibilité est cassée car l'API va changer en profondeur 13 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 14 La licence Zend Framework Zend Framework utilise une licence BSD Tout le monde peut l'utiliser, pour tout, sans conditions – point à la ligne « Business friendly » En même temps que la licence Framework elle-même, les contributeurs doivent signer un « Contributor License Agreement (CLA) » Protection de la Propriété Intellectuelle du Framework pour tous les contributeurs et utilisateurs Approche très similaire (voire identique) à la « Apache Software Foundation » formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Entièrement centré PHP5 Nécessite PHP 5.2.4 ou supérieur Afin de tirer le meilleur parti de PHP, utilisez toujours la dernière version Exploite pleinement les avantages du modèle objet de PHP5 Et il existe des bugs dans celui-ci dans certaines versions de PHP Bannissez PHP5.1, consultez les changelogs de PHP5.2 Toutes les constantes sont encapsulées dans des classes Pas de fonctions dans l'espace de nom global ZE2 / SPL pleinement utilisés là où cela a un sens Les fonctions de magie noire __magic() utilisées de façon parcimonieuse 15 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend Framework et orientation objet Utiliser ZendFramework brut est simple, mais l'utiliser de manière brute ne sert pas à grand chose. Il faut le comprendre pour le modifier et l'adapter à vos besoins, sans cesse en évolution Parfaite maitrise des concepts objets et du génie logiciel nécessaires Créer des structures objets très dynamiques, et proches de Java ou C++. Les design patterns sont vos amis ! Programmez par contrats (interface et abstraction) Les tests sont des atouts indispensables qu'il faut utiliser Pour avoir la culture et le "feeling" objet : faites du Java ou du C++ ! 16 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 17 Formation Zend Framework architecte A: Rappels sur le ZF 1. Les différents packages 2. Le niveau de couplage 3. Les versions et l'évolution du framework 4. Le futur de Zend framework B: Comprendre et maitriser MVC 5. Monter une application MVC 6. Gérer des bases de données 7. Monter un modèle 8. Formulaires, Authentification 9. Application et bootstrap 10. Pattern contrôleur frontal 11. Objets de requête et réponse 12. Routage 13. Vues, templates et Layouts 14. Plugins MVC et aides d'action 15. Aides de vues C: Ajax 16. Introduction à JQuery 17. ZendFramework et Ajax 18. Intégration dans les vues et les layouts D: Gérer la redondance des developpements 19. Génie logiciel, design patterns et UML 20. Couplage, cohésion et responsabilités 21. Utiliser le débogueur pour comprendre le code 22. Créer son propre framework sur ZendFramework E. Testabilité 23. Rappels sur PHPUnit 24. Ecrire et automatiser le lancement des tests 25. Zend_Test et tests fonctionnels 26. Assertions sur le DOM F: Conclusions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mini application : BDD d'exemple 18 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mini-application MVC Voici l'application à monter Elle n'est esthétiquement pas jolie, mais ce n'est pas une priorité Nous pourrons toujours la rendre plus jolie plus tard 19 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mini-application MVC Montez cette application, de manière "classique" et surtout simple La page d'accueil avec les stats sur les ouvrages La liste des ouvrages ("nos ouvrages") L'ouverture d'un compte dans la bibliothèque (inscription) 20 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Traiter avec XML et JSON, le cas PHP Rappels sur les possibilités XML natives de PHP Dom SimpleXML XmlReader XmlWriter Sax Possibilités JSON json_encode() json_decode() 21 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 22 Traiter avec XML et JSON, ZendFramework Zend_Dom_Query Requête le DOM grâce à Xpath ou aux selecteurs CSS Proche des manières d'interroger le DOM avec les framework Javascript ($ ()) Zend_Feed Consommation de flux XML de types Atom, RSS, ou personnalisés Zend_Json Propose un encodeur et un décodeur Plusieurs formats gérés : XML, objet PHP, tableau PHP etc... formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Soap Services Webs Zend_Soap_Server Zend_Soap_Client Zend_Soap_Wsdl Zend_Soap_Autodiscover Zend_Rest Zend_Rest_Server Zend_Rest_Client Zend_Rest_Controller Zend_XmlRpc Zend_XmlRpc_Server Zend_XmlRpc_Client 23 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 24 Services Webs Notre bibliothèque en ligne n'est pas très riche en ouvrages, néanmoins nous avons décidé de partager ceux-ci via un service Web Un choix s'offre à nous : SOAP, XML-RPC ou REST ? Quoiqu'il en soit, le serveur devra Soit être logé dans un contrôleur spécial Soit être logé à coté de la règle de réécriture et autonome Cette solution est plus performante Elle évite une boucle MVC lourde Elle permet de jouer avec le cache HTTP plus simplement formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Services SOAP Zend_Soap simplifie la gestion des services SOAP par rapport à PHP Surtout concernant la génération et le maintient à jour du WSDL ! Première chose : vérifier la présence de ext/soap dans PHP Sinon l'installer Ensuite, loger son service hors MVC /html/services/soapserver.php 25 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Service SOAP : classe d'exemple Un exemple tout simple de classe à partager class LivresService { /** * @param string $what * @return array */ public function listage($what) { return array('livre 1', 'livre 2', 'livre 3'); } /** * @param array $data Données * @return bool */ public function add(array $data) { if (isset($data['titre'])) { return true; } return false; } } 26 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 27 Découverte et génération WSDL PHP contrairement à Java, est faiblement typé La génération du WSDL ne peut se faire que si les tags PHPDocumentor de la classe sont correctement écrits L'auto-générateur va utiliser la reflection PHP (Zend_Server_Reflection) pour analyser ceux-ci et en déduire les types SOAP à gérer (SoapVar) Utilisez ensuite Zend_Soap_AutoDiscover $wsdl = new Zend_Soap_AutoDiscover(); $wsdl->setClass('LivresService'); $wsdl->setUri("path/to/soap/server.php"); $wsdl->handle(); handle() va générer une réponse XML de type WSDL, celui-ci sera toujours calqué sur la classe analysée, donc toujours à jour. formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 28 Zend_Soap : utilisation L'utilisation de Zend_Soap_Server/client est très proche de celle de PHP natif (SoapServer et SoapClient) On rajoute simplement quelques options (cf doc) $soap = new Zend_Soap_Server("path/to/Wsdl'); $soap->setClass('LivresService'); $soap->handle(); class LivresService { /** * @param string $what * @return array */ public function listage($what) { return array('livre 1', 'livre 2', $what); } /** * @param array $data Données * @return bool */ public function add(array $data) { if (isset($data['titre'])) { return true; } return false; } $client = new Zend_Soap_Client("path/to/wsdl); var_dump($client->listage('anaska')); // array('livre 1', 'livre 2', 'anaska') } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 29 Formation Zend Framework expert certifié A: Rappels sur le ZF 1. Les différents packages 2. Le niveau de couplage 3. Les versions et l'évolution du framework B: Préparer la certification 4. Objectifs de la certification 5. Domaines de compétences testés 6. Exemples types de questions C: Projet de mini application 7. Monter une application MVC 8. Gérer des bases de données 9. Formulaires 10. Authentification, sécurisation et ACLs 11. Services webs et flux XML D: Comprendre et maitriser MVC 12. Pattern contrôleur frontal 13. Vues, templates et Layouts 14. Plugins MVC et aides d'action 15. Aides de vues E: Ajax 16. Introduction à JQuery 17. ZendFramework et Ajax 18. Intégration dans les vues et les layouts F: Gérer la redondance des developpements 19. Génie logiciel, design patterns et UML 20. Couplage, cohésion et responsabilités 21. Utiliser le débuggeur pour comprendre le code 22. Créer son propre framework sur ZendFramework G. Testabilité 23. Rappels sur PHPUnit 24. Ecrire et automatiser le lancement des tests 25. Zend_Test et tests fonctionnels H: Conclusions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 30 Modèle MVC de ZendFramework Le but est de comprendre en profondeur tout le modèle MVC du ZendFramework Ceci va réellement vous aider à monter des applications Plus découplées Plus maintenables Plus robustes, testables ZendFramework propose tout ce qu'il faut pour cela. Savez-vous ce que sont Le contrôleur frontal ? Le dispatcheur (aiguilleur) Les aides d'action ? Les vues et les layouts ? formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 31 Objets MVC : Attention :beaucoup d'objets entrent en jeu ! Ils sont couplés plus ou moins fortement FrontController ActionController Request Object Response Object Tous ces objets jouent ensemble Router Une articulation très précise Dispatcher On peut intervenir à l'étage que l'on souhai Action Helpers Action helper broker FrontController plugins FrontController plugins broker formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Classes MVC sous ZF : 32 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Articulation MVC 33 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Processus MVC : 34 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Loader_Autoloader Chargement auto. des classes 35 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Chargement auto. des classes L'autoload est une fonctionnalité PHP de chargement automatique des classes L'autoload utilise un loader concernant la règle de nommage du ZendFramework : Zend_Loader::loadClass() Chaque underscore de classe se transforme en slash dans le système de fichier Zend_Controller_Dispatcher_Standard => Zend/Controller/Dispatcher/Standard.php (Le dossier Zend doit être dans l'include_path de PHP) Pour la suite de cette formation nous supposerons que l'autoload est activé require 'Zend/Loader/Autoloader.php'; Zend_Loader_Autoloader::getInstance(); // activation de l'autoload 36 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 37 Autoloader L'autoloader charge les classes Zend_ et ZendX_ par défaut, et c'est tout Pour charger d'autres types de classes, enregistrez leur dossier dans l'include_path de PHP Et enregistrez leur espace de noms dans l'autoloader require 'Zend/Loader/Autoloader.php'; set_include_path(get_include_path() . PATH_SEPARATOR . 'path/to/libs'); $autoload = Zend_Loader_Autoloader::getInstance(); $autoload->registerNamespace('Anaska'); $obj = new Anaska_Utils; registerNamespace() enregistre Zend_Loader_Autoloader comme autoloader pour un espace de nom spécifié Zend_Loader_Autoloader utilise le loader Zend_Loader::loadclass() par défaut formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Autoloader de ressources 38 Les autoloaders de ressources servent à charger des ressources (des classes) qui ne respectent pas strictement la règle par défaut "les underscores donnent des slashs" mais permettent un mapping personnalisé $resourceLoader = new Zend_Loader_Autoloader_Resource(array( 'basePath' => 'path/to/libs', 'namespace' => 'Anaska', 'resourceTypes' => array( 'acl' => array( 'path' => 'acl', 'namespace' => 'Acl'), 'form' => array( 'path' => 'models/forms', 'namespace' => 'Form'), 'models' => array( 'path' => 'models/tables') ))); $a = new Anaska_Acl_MyAcl $b = new Anaska_Form_MyForm $c = new Anaska_MyTable formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Fonctionnement des autoloaders Les différents loaders s'empilent dans Zend_Loader_Autoloader Le loader par défaut est Zend_Loader::loadClass() Grâce au namespace, Zend_Loader_Autoloader sait quel loader utiliser pour quelle classe Vous déclarez un namespace de 2 manières : Via registerNamespace() En utilisant Zend_Loader_Autoloader_Resource Pour gérer les loaders, plusieurs méthodes s'offrent à vous : $autoload->pushAutoloader($autoloader, $namespace); $autoload->unshiftAutoloader($autoloader, $namespace); $autoloader peut être de la forme : * Zend_Loader_Autoloader_Interface * array('Class','Method_Statique_D'autoload') * function Ma_Fonction_Autoload($class) $autoloader->removeAutoloader($autoloader, $namespace) 39 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 40 Fonctionnement des autoloaders Le système de chargement est intelligent et économique au maximum Il est aussi extrêmement fléxible et permet de lier le projet à n'importe quelle structure existante en ajoutant son loader à la pile Un autoloader de ressource tout prêt existe déjà : Zend_Application_Module_Autoloader formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Chargeur personnalisé Zend_Loader_PluginLoader est une classe qui permet de charger vos propres classes si vous ne souhaitez pas les ajouter à l'include_path Attention, il ne s'agit plus de chargement automatique require 'Zend/Loader/PluginLoader.php'; $loader = new Zend_Loader_PluginLoader(); $loader->addPrefixPath('Anaska', 'libs/Anaska'); $obj = $loader->load('Utils'); PluginLoader est surtout utilisé en interne par des objets du Zend Framework afin de vous permettre de remplacer ses dépendances par les votres PluginLoader admet plusieurs couples préfixes/chemins , lors du chargement il cherche dans la pile dans l'ordre LIFO 41 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Application 42 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Application Comme vous le constatez, nous commençons à posséder beaucoup d'objets Tous se configurent de manière différente Le seul facteur commun est un objet Zend_Config Zend_Application est un composant dont les rôles sont : Uniformiser la création des objets et leur configuration Enregistrer un Autoloader automatiquement Configurer tous les paramètres PHP.INI simplement (ini_set) Gérer le changement d'environnement (prod/dev) facilement Faciliter la configuration de MVC Gérer les dépendances entre les objets 43 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 44 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Application : exemple config.php (deviendra index.php en MVC): define ('APP_ENV', 'dev'); define ('APP_PATH', realpath(__DIR__)); require_once 'Zend/Application.php'; $app = new Zend_Application(APP_ENV, APP_PATH .'/config/application.ini'); application.ini : [app] phpsettings.soap.wsdl_cache_enabled = 1 includepaths[] = APP_PATH "/model" includepaths[] = APP_PATH "/foo/bar" autoloadernamespaces[] = "Form" autoloadernamespaces[] = "Table" [dev:app] phpsettings.display_errors = 1 [prod:app] phpsettings.display_errors = 0 45 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 46 Zend_Application Le premier paramètre sera la section du config.ini à charger : $app = new Zend_Application(APP_ENV, APP_PATH .'/config/application.ini'); Ces clés sont automatiquement reconnues et parlent d'elles-mêmes: [app] phpsettings includepaths autoloadernamespaces Un Zend_Loader_Autoloader est automatiquement crée par Zend_Application, vous pouvez via le fichier de config., ajouter des "namespaces" La simple création d'un objet Zend_Application exécute toute cette configuration automatiquement, si présente dans le fichier de config. formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Application : exercice Reprenez notre fichier de configuration Intégrez-y Zend_Application [app] phpsettings includepaths autoloadernamespaces 47 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 48 Zend_Application et bootstrap Nous n'avons fait "que" configurer des options basiques Il faut maintenant configurer nos objets utiles pour la suite (Cache, Db, Session, etc...) Cette tâche va être déléguée à "un bootstrap" : c'est une classe Au plus simple; une classe étendant Zend_Application_Bootstrap_Bootstrap [app] bootstrap.path = APP_PATH "/bootstrap.php" bootstrap.class = MyBootstrap Zend_Application charge la configuration de base Zend_Application_Bootstrap_Bootstrap charge la configuration des objets dont nous allons avoir besoin formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 49 Zend_Application, bootstrap et config Dès lors il devient possible de configurer des objets de ZF, appelés "resources" On crée une méthode protégée _initNomDeLaRessource() dans la classe bootstrap On configure l'objet dedans, puis on le retourne le bootstrap a accès aux options de config.ini (getOption()) class MyBootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initLog() { $log = new Zend_Log(); $logOptions = $this->getOption('log'); $log->addWriter(new Zend_Log_Writer_Stream($logOptions['file'])); return $log; } } [dev:app] log.file = mylog.log formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Application, bootstrap et config On peut alors maintenant "charger" notre ressource Puis la récupérer Ceci depuis l'objet Application ou Bootstrap //$app est l'objet Zend_Application $bootstrap = $app->getBootstrap(); $bootstrap->bootstrap('log'); // passe dans la méthode _initLog() // s'écrit aussi $bootstrap->bootstrapLog() $log = $bootstrap->getResource('log'); récupère l'objet configuré // s'écrit aussi $log = $bootstrap->log; class MyBootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initLog() { $log = new Zend_Log(); $logOptions = $this->getOption('log'); $log->addWriter(new Zend_Log_Writer_Stream($logOptions['file'])); return $log; } } 50 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 51 Particularité du bootstrap En plus de "proposer de ranger sa configuration concrête des objets", le bootstrap assure leur stockage Il ne faut pas oublier de charger la ressource Si vous la chargez plusieurs fois, aucun problème : le chargement réel ne sera effectué qu'une seule fois $bootstrap->bootstrapLog(); $bootstrap->bootstrapLog(); // un processus évite le "rechargement", pas d'exception Bootstrap agit comme un registre à objets donc : besoin de l'objet de log quelque part ? $bootstrap->log; formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr bootstrap de tous les objets Il serait intéréssant de lancer le bootstrap de tous les objets d'un coup Ils seront alors tous disponibles, sans se poser de question Appelez bootstrap() sans aucun paramètre pour cela : $bootstrap->bootstrap(); // charge tous les objets définis Ceci charge toutes les ressources dans l'ordre de leur apparition dans le bootstrap On ne se pose plus la question de savoir si l'objet est chargé : il l'est $log = $bootstrap->log; $db = $bootstrap->db;... 52 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Gestion des dépendances Et si notre Log avait besoin d'un objet de base de données ? class MyBootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initDb() { return Zend_Db::factory(new Zend_Config($this->getOption('db'))); } protected function _initLog() { $log = new Zend_Log(); $this->bootstrapDb(); // on charge l'objet db (passe dans _initDb()) $db = $this->db; // on le récupère $log->addWriter(new Zend_Log_Writer_Db($db, 'logtable')); return $log; } } C'est un mécanisme de gestion des dépendances intuitif et simple 53 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Application : exercice Passez toute notre configuration utilisée jusqu'à présent au format Zend_Application Log, Db, Session, Cache ... 54 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Bootstrap : plugins de ressources Quel est le problème de ces méthodes _initXYZ() ? Elles sont difficilement portables et évolutives, de projet en projet, ou de module en module (voir MVC) Il existe un autre moyen de configurer ses ressources Via des classes, réutilisables donc Des Zend_Application_Resource_ResourceAbstract Il en existe déjà certaines livrées dans ZF Db, Session, FrontController, Cache, View, Modules, Layout, Locale, Log, Router, Translate, Navigation, Mail, MultiDb ... 55 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 56 Utiliser les plugins de ressources existants Vous ne spécifiez pas de méthode _initLaRessource() Vous préfixez ses paramètres dans la config. générale, par le mot "resources." Ses paramètres se trouvent dans la doc ou la source des plugins class MyBootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initLog() { $log = new Zend_Log(); $this->bootstrapDb(); // le plugin existe déjà dans ZF $db = $this->db; $log->addWriter(new Zend_Log_Writer_Db($db, 'logtable')); return $log; } } [dev:app] ... ... resources.db.adapter = pdo_mysql resources.db.params.host = 127.0.0.1 resources.db.params.username = julien resources.db.params.password = anaska resources.db.params.dbname = mle resources.db.isDefaultTableAdapter = true formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 57 Fonctionnement des plugins de ressources Lorsque la configuration contient le mot resources. le framework considère le plugin correspondant, lui passe la configuration et invoque sa méthode init() ... ... resources.db.adapter ... = pdo_mysql class Zend_Application_Resource_Db extends Zend_Application_Resource_Abstract { public function init() { Zend_Db::factory(...); } } Le plugin construit alors l'objet considéré resources.db Zend_Application_Resource_Db Zend_Db formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 58 Exercice : utiliser les plugins Refactorisez pour utiliser les plugins du Zend Framework Veillez à préfixer leur configuration de resources. pour les faire intervenir Veillez aussi à supprimer la méthode _initxxx() Un objet ne doit pas avoir 2 manières différentes d'être configuré (plugin + méthode _init() Il est possible de créer vos propres plugins Il faut étendre Zend_Application_Resource_ResourceAbstract formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Partage du bootstrap Zend_Application_Bootstrap_Bootstrap partage l'objet de bootstrap dans le contrôleur frontal $front->setParam('bootstrap', $bootstrap); Vous pouvez donc le récupérer n'importe où, et en utiliser les objets class IndexController extends Zend_Controller_Action { public function indexAction() { $log = $this->getInvokeArg('bootstrap')->getResource('log'); } } // ou encore $bootstrap = Zend_Controller_Front::getInstance()->getParam('bootstrap') Analysons le code de Zend_Application_Bootstrap_Bootstrap 59 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Gestion de la vue Zend_View est l'objet de vue Il est découplé de la partie contrôleur Il sert simplement à séparer les variables de contrôles de celles d'affichage Zend_View utilise 4 dossiers ScriptPath : les scripts de vue FilterPath : les filtres des variables de vue HelperPath : les aides de vue (opérations communes) BasePath : le dossier qui contient les 3 autres /filters /helpers /scripts 60 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_View Zend_View ne sert qu'à séparer les syntaxes de contrôles de celles d'affichage $view = new Zend_View; $view->setBasePath('basepath'); $view->maVar = "anaska"; echo $view->render('script1.phtml'); //script1.phtml echo $this->maVar; Les scripts de vue possèdent l'extension .phtml (convention) On utilise dedans les variables précédemment affectées, avec $this->variable 61 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_View : options Zend_View peut filtrer les variables de vue qui lui sont passées : echo $this->escape($this->maVar); Par défaut, htmlspecialchars() est utilisé avec l'encodage ISO-8859-1 setEncoding() et setEscape() permettent de changer celà function mafonction($v) { return htmlentities(trim($v)); } $view->setEscape('mafonction'); echo $this->escape($this->maVar); 62 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 63 Zend_View : options clearVars() détruit toutes les variables affectées à la vue à ce stade getVars() retourne un array avec toutes les variables de vues affectées à ce stade strictvars(true) permet de vous informer si vous utilisez une variable de vue non initialisée dans le script de contrôle $view->strictVars(true); echo $this->nexistepas // Notice : undefined variable nexistepas Toutes les options de la vue peuvent se passer d'un coup à son constructeur Zend_Application_Resource_View tire parti de celà resources.view.basePath = '/my/path/to/views' resources.view.strictVars = 1 resources.view.encoding = "UTF-8" resources.view.escape = "nom-de-ma-fonction" formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_View : aides de vue Les opérations rébarbatives dans les vues peuvent être factorisées Sous forme de classes étendant Zend_View_Helper_Abstract Elles doivent avoir un nom Zend_View_Helper_MonAide Elles doivent posséder une méthode publique monAide() Elles doivent se trouver dans un dossier d'aides (helperPath) On les appelle alors sous forme de méthodes sur la vue class Zend_View_Helper_MonAide extends Zend_View_Helper_Abstract { public function monAide($var) { return "Anaska aide de vue écrit $var"; } } echo $this->monAide('foo'); // Anaska aide de vue écrit foo 64 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_View : aides de vue intégrées Outre vos propres dossiers helperPath, ZF ajoute aussi le sien à Zend_View Zend/View/Helpers Regardez toutes les aides disponibles ! 65 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_View : placeholder Placeholder permet de définir une variable dans un conteneur Ce conteneur va persister au travers la vue et la layout Ce conteneur peut être de type tableau Les valeurs peuvent être séparées et répétées Un simple echo sur l'objet l'affiche $this->placeholder('titre')->set('Mon Titre'); $this->placeholder('titre')->setPrefix('<h1>')->setPostfix('</h1>'); echo $this->placeholder('titre'); // <h1>Mon Titre</h1> $data = array('point1', 'point2'); $this->placeholder('items')->exchangeArray($data); $this->placeholder('items')->setIndent(4)->setSeparator("\n"); echo $this->placeholder('items'); 66 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 67 Zend_View : placeholders concrêts Il existe déjà des aides de vues qui étendent placeholder HeadStyle, HeadScript, HeadTitle, HeadLink, HeadMeta echo $this->headLink()->appendStylesheet('/css/media.css'); echo $this->headTitle('titre1')->append('titre2')->setSeparator('/'); echo $this->headScript()->appendFile('js/prototyype.js'); Vous pouvez aussi capturer du contenu depuis le buffer PHP avec captureStart() captureEnd() Les possibilités sont immenses http://framework.zend.com/manual/en/zend.view.helpers.html formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_View dans MVC Zend_View est intégrée dans les composants MVC de ZF grâce à un objet appelé ViewRenderer Celui-ci se charge de crée l'objet de vue et de lui passer des options Il se charge entre autre d'affecter le basePath de la vue Il se charge aussi de créer un chemin vers le script de vue views/scripts/{nom-du-contrôleur}/{nomaction}.phtml Bien sûr, tout est personnalisable, ceci représente simplement la structure par défaut Jouer avec ViewRenderer, c'est personnaliser tout le processus d'automatisation de l'intégration de la vue dans MVC 68 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 69 Zend_Layout La layout permet de rendre le contenu d'une vue dans une vue plus globale Ceci permet d'habiller le site (header, footer, menus et contenu) Le système de Layout travaille en duo avec la vue Zend_View On rend sa vue normalement, mais sans l'afficher, on la rend dans une variable de layout On demande le rendu de la layout Dans le script de layout, on précise où l'on place le rendu de la vue précédemment effectué Il s'agit d'un pattern "two step view" formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 70 Zend_Layout // Création de la layout $layout = new Zend_Layout(array('layoutPath'=>'path/to/layouts', 'layout'=>'main')); // Création de la vue $view = new Zend_View(array('basePath'=>'path/to//views')); // partage de la vue à la layout $layout->setView($view); // Rendu de la vue dans une variable de la layout $layout->content = $view->render('vue.phtml'); // Affichage de la layout echo $layout->render(); Ici, la layout s'appelle main.phtml : <div class="header"> HEADER ICI </div> // Affichage du contenu de la vue rendue précédemment dans une variable de layout appelée "content" <div class="content"> <?php echo $this->layout()->content; ?> </div> <div class="footer"> FOOTER ICI </div> formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Layout dans MVC Grâce à l'objet ViewRenderer, le partage de l'objet de vue à la layout est automatique Aussi, dans le système MVC, le rendu de la layout tout comme celui de la vue est effectué automatiquement (désactivable) si Zend_Layout est activé 71 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Controller_Front 72 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 73 Zend_Controller_Front Zend_Controller_Front implémente le motif Front Controller utilisé dans les applications MVC. Il : Initialise l’environnement de requête Passe les requêtes entrantes au routeur pour découverte d'action Passe au dispatcheur la requête pour traitement de l'action Contient l'objet de réponse, rempli par les contrôleurs via les vues Envoi l'objet de réponse à la fin du processus Singleton (une seule instance disponible) Enregistre un gestionnaire de plugins Requiert au minima un ou plusieurs chemins vers des répertoires contenant les Action Controller Charge l'action helper ViewRenderer Charge le plugin ErrorHandler formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 74 Zend_Controller_ Front Configurer le modèle MVC dans son ensemble Vous cherchez un objet ? Il le connait formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 75 Zend_Controller_Front Contient la boucle de dispatching C'est une boucle do { } while(); Elle fait tourner l'objet de requête et de réponse formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 76 Contrôleur frontal : intéressant Il pilote et gère tous les objets, s'ils n'existent pas au début du process, il va les créer lui-même, sinon on peut lui passer les notres setRequest(), setResponse(), setDispatcher(), setRouter() ... Il ne renvoie pas les exceptions qu'il attrape éventuellement par défaut Il les rajoute dans l'objet de réponse qui en est un conteneur Sauf si on le lui indique explicitement : throwExceptions(true) Il connait les contrôleurs, et les modules contenant les contrôleurs setControllerDirectory(), setModuleDirectory(), addControllerDirectory() Il peut propager des paramètres dans le système MVC (pour le routeur ou le dispatcheur en général) setParam(), setParams() formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr try { $this->_plugins->routeStartup($this->_request); $router->route($this->_request); $this->_plugins->routeShutdown($this->_request); $this->_plugins->dispatchLoopStartup($this->_request); do { $this->_request->setDispatched(true); $this->_plugins->preDispatch($this->_request); if (!$this->_request->isDispatched()) { continue; } try { $dispatcher->dispatch($this->_request, $this->_response); } catch (Exception $e) { if ($this->throwExceptions()) { throw $e; } $this->_response->setException($e); } $this->_plugins->postDispatch($this->_request); } while (!$this->_request->isDispatched()); } catch (Exception $e) { if ($this->throwExceptions()) { throw $e; } $this->_response->setException($e); } 77 Code de la boucle de dispatching formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Request L’objet Request contient tout ce dont vos contrôleurs auront besoin de récupérer en provenance de la requête HTTP variables GET/POST COOKIE SERVER / ENV Informations sur le chemin : baseUrl, basePath Contrôleur et action à dispatcher Jeton de dispatching (isDispatched) L'objet de requête est le point d'entrée de l'application 78 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Request 79 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Request Le plus important, certainement, est le jeton de dispatching Propriété $_dispatched et méthode isDispatched() Si à False : il indique au contrôleur frontal que la requête contenue dans l'objet n'a pas encore été traitée Une autre itération de la boucle est donc nécessaire Rappelez vous : try { // bla bla bla do { $this->_request->setDispatched(true); // bla bla bla } while (!$this->_request->isDispatched()); } catch (Exception $e) { // bla bla bla 80 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 81 Request L'objet de requête, lorsque routé, contient aussi le "trio remarquable" de MVC $_module $_controller $_action Ces attributs vont être utilisés par le dispatcheur afin de trouver le bon contrôleur et lancer la bonne action formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 82 Routeur Le Routeur est responsable de la décomposition de l’URL et de la détermination du trio module/ctrl/action à exécuter Il utilise donc l'objet de requête, et c'est tout ! Apache doit utiliser mod_rewrite pour tout diriger vers le contrôleur frontal, l'objet routeur se charge alors de l'URL à la place du serveur Web On lui ajoute des routes sous forme d'objets Zend_Controller_Router_Route_Interface Il teste les routes sur l'URL dans l'ordre LIFO, la première qui matche arrête les tests et renseigne l'objet de requête avec une action à exécuter formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 83 Routeur formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Routeur Souvenez vous de la boucle de dispatching try { // bla bla bla $router->route($this->_request); // bla bla bla do { // bla bla bla } while (!$this->_request->isDispatched()); } catch (Exception $e) { // bla bla bla } Derrière la méthode route(), un processus complexe Utilisant des regexp Jouant avec le PathInfo de la requête Des tests sont obligatoires pour utiliser un routage complexe Proche, plus ou moins, du routage Apache avec mod_rewrite (regexps) 84 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mise en place du routage Séparez le dossier "application" du dossier "public" Créez un vhost pour encapsuler le client dans le dossier public Créez une règle de réécriture dirigeant sa requête sur "index.php" /etc/hosts 127.0.0.1 localhost zfapp <virtualhost *:80> servername localhost documentroot /var/www </virtualhost> httpd.conf <virtualhost *:80> servername zfapp documentroot /var/www/zfapp/public <directory /var/www/zfapp/public> RewriteEngine On RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l [OR] RewriteCond %{REQUEST_FILENAME} -d RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L] </directory> </virtualhost> 85 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Routage par défaut Par défaut : http://mon-hote/[base-url]/[module]/[controller]/[action]/[params] Sur un vhost, baseurl = null Sur des applications simples : module = null http://zfapp/membres/liste/page/3 class MembresController extends Zend_Controller_Action { public function listeAction() { $this->_getParam('page'); // 3 } } La vue views/scripts/membres/liste.phtml sera rendue 86 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 87 Routage : création d'une route La route par défaut est une Zend_Controller_Router_Route_Module Le routeur détermine d'abord le "base-url", c'est à dire l'URL à partir de laquelle il va commencer son analyse Apache utilise le même principe pour mod_rewrite Dans le cas d'un hôte virtuel Apache, elle vaut 'null' http://host/default/membres/liste/page/4 http://host/appli/www/default/membres/liste/page/4 Pour des raisons de performance, de sécurité et aussi de simplicité, il est fortement conseillé d'utiliser un hôte virtuel formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 88 Création d'une route Le routeur est unique, actuellement : Zend_Controller_Router_Rewrite Il encapsule des routes, qui sont nommées Par défaut, il n'existe qu'une seule route, son nom est 'default' $route = new Zend_Controller_Router_Route_Module(array(), $dispatcher,$request); $this->addRoute('default', $route); On va lui rajouter une(des) routes, en prenant garde de ne pas supprimer ou écraser la route à l'index 'default', sinon le routage par défaut que nous connaissons bien ne fonctionnera plus Attention, les routes sont analysées en ordre LIFO, et la première qui matche est choisie Insérez vos routes de la plus spécifique, à la plus générique formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Création et gestion d'une route Qu'est ce qu'une route ? Généralement une regexp (expression régulière) Mais pas tout le temps ( voir doc officielle) Cette regexp doit capturer et définir les clés 'module', 'controller', 'action', 'foo' (n'importe quelle clé qui sera alors considérée comme un paramètre) http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes Pour récupérer la route en cours d'utilisation : $router->getCurrentRouteName(), ou l'objet route : $router->getCurrentRoute() 89 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Dispatcher Le Dispatcher est responsable du lancement de l'action En Français on peut le traduire "aiguilleur" Il récupère l'objet de requête fraichement routé, et analyse son trio module/ctrl/action Trouve le fichier contrôleur Crée une instance de la classe contrôleur à exécuter Puis appelle sa méthode dispatch() Initialise le contrôleur et les aides d'action Appelle init() et créer un gestionnaire d'aide (HelperBroker) Formate les noms des contrôleurs et des actions (casse) Si contrôleur non trouvé, utilise un contrôleur par défaut si on le lui demande 90 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Dispatcher 91 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 92 Paramètre du dispatcheur Le dispatcheur par défaut est un Zend_Controller_Dispatcher_Standard PrefixDefaultModule Préfixe le nom du module pour le module par défaut aussi UseDefaultControllerAlways Si le contrôleur est introuvable, n'envoie pas d'exception, considère le contrôleur par défaut (par défaut : index) DisableOutputBuffering Désactive la capture des fuites d'affichage dans les contrôleurs // Directement au dispatcheur $dispatcher->setParam('prefixDefaultModule', true) ; // Au contrôleur frontal, qui propagera $front->setParam('prefixDefaultModule', true) ; formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 93 Action controller Finalement, le contrôleur d'action est exécuté lorsque le Dispatcher crée son instance et appelle sa méthode dispatch() Tout contrôleur doit étendre Zend_Controller_Action Qui dispose, entre autre, d'une méthode dispatch() Le contrôleur d'action est créé par le développeur de l’application Il contient une partie de la logique applicative Personnaliser les contrôleurs d'action permet une très forte réutilisation du code Nous allons y venir formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 94 Action controller formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Pratique dans un contrôleur Accès à la vue: $this->view Accès à la layout : $this->_helper->layout() Effectuer une redirection HTTP : $this->_redirect('/foo/bar'); $this->_helper->redirector('action', 'ctrl'); Accès au bootstrap : $this->getInvokeArg('bootstrap') Accès aux paramètres de la requête (params, get ou post): $this->_getParam('foo'); 95 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Exercices intermédiaires Mettez en évidence le processus de routage de l'objet de requête Voyez que le routeur remplit bien le trio remarquable mod/ctrl/action Comment créer la boucle infinie de dispatching la plus simple dans MVC ? Oui, ca paraît idiot, mais ça peut arriver si on ne prend pas garde Détaillez le fonctionnement de Zend_Controller_Action::_forward() et Zend_Controller_Action::_redirect() Quelles sont les différences fondamentales entre ces 2 appels ? 96 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 97 Séquence générale Le Dispatcher tourne dans une boucle, vous permettant d’appeler plusieurs actions Contrôleur en une seule requête Cela s’appelle la "boucle de dispatching" Vous permet de scinder votre application en classes logiques au lieu de vous forcer à écrire une seule classe / méthode pour chaque requête URI Ex : Un Contrôleur Login est exécuté après le Contrôleur Business formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 98 Plugins Le contrôleur frontal permet l'enregistrement de plugins Ils doivent étendre Zend_Controller_Plugin_Abstract registerPlugin() , unregisterPlugin() Ils servent à rajouter, ou enlever des fonctionnalités, dans le modèle MVC, sans devoir étendre des classes Ils ont directement accès à l'objet de requête et de réponse, c'est tout Très puissant, mais attention aux effets de bord ! Ils "écoutent" sur 6 évènements chronologiques ZF utilise déjà des plugins pour lui même, regardez leur fonctionnement ErrorHandler Layout (si vous activez les Layouts) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 99 Plugins et boucle de dispatching try { $this->_plugins->routeStartup($this->_request); $router->route($this->_request); $this->_plugins->routeShutdown($this->_request); $this->_plugins->dispatchLoopStartup($this->_request); do { $this->_request->setDispatched(true); $this->_plugins->preDispatch($this->_request); if (!$this->_request->isDispatched()) { continue; } try { $dispatcher->dispatch($this->_request, $this->_response); } catch (Exception $e) { // bla bla bla } $this->_plugins->postDispatch($this->_request); } while (!$this->_request->isDispatched()); } // bla bla bla try { $this->_plugins->dispatchLoopShutdown(); // bla bla bla Commentez la boucle de dispatching et la gestion des plugins Pourquoi routeShutdown() et dispatchLoopStartup() se suivent-ils ? Quel est leur sens ? Avez vous des idées de plugins en tête ? formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 100 Plugins et ordonnancement "Pour chaque plugin effectuer telle méthode" Chaque plugin ? Dans quel ordre ? Il faut mémoriser les plugins, et leur ordre de traitement est extrêmement important ! Pourquoi ? La gestion de l'ordre des plugins et de leur apparition est déléguée à un objet attaché au contrôleur frontal Zend_Controller_Plugin_Broker Analysez le, déterminez son rôle formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Exercice Plugins Analysez le fonctionnement du plugin ErrorHandler Que peut-on dire à son sujet ? Créez un plugin anti boucles infinies de dispatching Au bout de "n" boucles détectées, on doit en sortir avec une Exception "n" est configurable 101 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 102 Response A l'autre bout de la chaine MVC se situe la réponse : c'est un objet L’objet Response est décomposé en 'body' et 'headers' Le 'body' est rempli par les vues rendues par vos contrôleurs, il est lui même décomposé en segments Le rendu de la réponse envoie tous les en-têtes vers Apache, suivi du contenu du 'body'. La réponse contient aussi les exceptions que le moteur MVC va rencontrer éventuellement formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Response 103 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 104 Aides d'action Tout code commun à plusieurs contrôleurs d'action doit être factorisé Un gestionnaire d'aide est ajouté à chaque contrôleur d'action par le dispatcheur Récupérable par $this->_helper Implémente __get et __call Puis un pattern Strategy Permet le chargement des aides à la volée Chaque aide est une classe et étend Zend_Controller_Action_Helper_Abstract Chaque aide reçoit une instance du contrôleur d'action pour interagir avec Il existe des aides par défaut ViewRenderer / Url / Redirector / ContextSwitch ... formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 105 Aides d'action formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 106 Aides d'action : exercices Quelle est la principale différence entre une aide d'action et un plugin MVC ? Quels sont les rôles de HelperBroker ? Comment gère-t-il la pile d'aide d'action enregistrées en lui ? Analysez le fonctionnement du duo plugin/aide d'action de Zend_Layout formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 107 Les aides d'action intégrées ViewRenderer La plus complexe sans doute But : rendre "la bonne vue" "au bon moment", pour toute action n'ayant pas dit le contraire Sert aussi de passerelle vers l'objet vue où que l'on se trouve Comment ? Calcul le chemin vers la vue Zend_View Configure Zend_View avec ses bons chemins (basePath) Injecte la vue dans le contrôleur en cours de dispatching Maitriser cette aide, c'est comprendre tout le processus d'affichage formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les aides d'action intégrées Redirector Gère les redirections HTTP Très proche de l'objet de réponse Remplit son code de retour, ses en-têtes Ferme proprement la session si démarrée Envoie l'objet de réponse fraichement rempli Suivi d'un exit(); (par défaut) 108 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les aides d'action intégrées FlashMessenger Enregistre des messages pour utilisation la fois suivante Typiquement des messages d'erreur Utilise la session pour effacer le message à la requête suivante 109 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 110 Les aides d'action intégrées Il en reste... AjaxContext ContextSwitch AutocompleteAjax AutocompleteScriptaculous Layout ... Comprendre la responsabilité et le fonctionnement d'une, c'est comprendre les autres, avec un peu de temps à prendre bien entendu formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 111 Zend_Layout Pattern "2-step view" : rendu d'une vue en 2 temps Un script de layout est une vue, il est rendu dans Zend_View Zend_Layout sert à gérer le fait que lorsque le dispatching est terminé, il faut trouver et rendre un script de layout après le rendu de la vue de l'action L'objet Zend_Layout est très semblable à un objet de vue Zend_Layout se sert d'un couple plugin/aide action pour fonctionner formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Layout Zend_Layout est liée à MVC au moyen d'un astucieux couple aide d'action/ plugin Elle est activée et injectée dans MVC grâce à startMvc() Ceci enregistre un couple aide/plugin Ce couple est changeable par vos propres objets Zend_Layout va chercher Zend_View en la demandant à ViewRenderer, sinon il faut lui passer une vue à la main 112 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 113 Zend_Layout L'aide d'action se charge de partager l'instance de Zend_Layout dans les contrôleurs et de proxier des appels vers Zend_Layout Le plugin se charge d'automatiser le rendu du Layout lorsque nécessaire (à la toute fin du dispatching) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 114 Exercices mini-application MVC Nous allons peu à peu enrichir notre application en fonctionnalités Vous allez voir que la tentation est grande de "poser le code" là où ça semble le plus logique de le déposer Il faudra toujours penser à la manière d'assembler ses objets De manière à ce qu'on ne se retrouve pas bloqués dans le futur formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 115 Pagination Le composant Zend_Paginator permet de paginer des données itératives Basé sur un simple pattern adaptateur, comme beaucoup de composants du Zend Framework formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 116 Zend_Paginator Crée un adaptateur selon la source de données Ou utilisez la méthode Zend_Paginator::factory($data) Zend_Paginator crée une fenêtre de visibilité paramétrable sur les données de l'adaptateur qu'il encapsule Propose une façade de pilotage des données, via itération entre autres Donne le moyen d'afficher, via une vue partielle, le contrôle de la pagination public function listeAction() { $TMembres = new TMembres(); $select = $TMembres->select(); $page = Zend_Paginator::factory($select); $page->setCurrentPageNumber($this->_getParam('page', 1)); $page->setItemCountPerPage($this->_getParam('par', 1)); $this->view->listeMembres = $page; } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 117 Zend_Paginator exemple Important : Zend_Paginator pilote l'adaptateur qu'il encapsule Nous, nous pilotons l'instance Zend_Paginator public function listeAction() { $TMembres = new TMembres(); $select = $Tmembres->select(); Zend_View_Helper_PaginationControl:: setDefaultViewPartial('pagination.phtml'); $page = Zend_Paginator::factory($select); $page->setCurrentPageNumber(3); $page->setItemCountPerPage(8); $this->view->listeMembres = $page; } <ul> <?php foreach ($this->listeMembres as $membre) { echo "<li>$membre->nom</li>"; } ?> </ul> <?php echo $this->listeMembres; Zend_Paginator implémente IteratorAggregate Qui délègue l'itération à l'adaptateur sous jascent Possède __toString : un affichage de l'objet affiche la vue partielle qui permet de naviguer dans la pagination formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 118 Zend_Paginator affichage du scrolling Pour utiliser le même script de vue pour toutes les données paginées, utilisez Zend_View_Helper_PaginationControl::setDefaultViewPartial() Changez le type de scrolling grâce à la méthode setDefaultScrollingType() Sliding (défault) $page->setDefaultScrollingStyle('Jumping') Jumping Elastic All Les types de scrolling définissent la manière dont l'affichage de la liste des pages va "glisser" au fur et à mesure que l'on avance. Pour bien le mettre en évidence, il faut un certain nombre de données à paginer ( ~ >20 ) Les Scrolling sont des objets Zend_Paginator_ScrollingStyle_Interface formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mini-application MVC La liste des ouvrages doit être paginée Utilisez Zend_Paginator dans ce but 119 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mini-application MVC Créez une route permettant d'y voir plus clair http://app/liste-des-livres-page-3-par-8 L'ancienne route fonctionne toujours, comment la désactiver ? 120 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 121 Authentification, session et formulaires formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Authentification Zend_Auth s'occupe de l'authentification Basée sur des adaptateurs Persistance dans un "storage", par défaut une session 122 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 123 Authentification : exemple base de données Zend_Auth_Adapter_DbTable($db, 'table', 'logincol', 'passcol', 'traitement') $adapter = new Zend_Auth_Adapter_DbTable($db, 'membres', 'login', 'pass', 'md5(?)'); $adapter->setCredential($pass) ->setIdentity($login); Authentification pure : $result = $adapter->authenticate(); Authentification avec persistance en session si OK : $result = Zend_Auth::getInstance()->authenticate($adapter); Le résultat est un objet Zend_Auth_Result : If ($result->isValid()) { echo $result->getIdentity(); } else{ var_dump($result->getMessages()); formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Présentation Zend_Form Implémente Zend_Validate_Interface Agrège des Zend_Form_Element Implémentant Zend_Valide_Interface Agrégeant des décorateurs Agrège des décorateurs Se compose de sous formulaires Zend_Form Design pattern composite Se compose de DisplayGroups Servant à présenter un groupe d'éléments d'une certaine manière Se composant de Zend_Form_Elements Se composant de décorateurs de groupe 124 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Un exemple simple Zend_Form n'est pas très intuitif à prendre en main à première vue Surtout lorsqu'il s'agit de présenter visuellement les éléments Pas de panique, ce composant est aussi logique que les autres Il est simplement un peu touffu, mais terriblement puissant 125 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Form UML 126 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Form : attributs 127 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 128 Fonctionnement Zend_Form a besoin d'une vue Zend_View pour s'afficher Il l'utilise afin de trouver les aides de vue (ViewHelpers) représentant les Zend_Form_Element Il récupère cette vue depuis le système MVC Nul besoin d'en créer une spécifiquement dans ce cas là Au plus simple, Zend_Form se compose d'éléments Le rendu du formulaire est le rendu de tous les éléments dans l'ordre dans lequel ils ont été ajoutés (ou spécifié manuellement) Chaque élément peut contenir des validateurs Chaque élément est rendu grâce à des décorateurs formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Exemple de formulaire Un simple echo devant l'objet Zend_Form l'affiche $form = new Zend_Form; $form->setView(new Zend_View); $form->addElements(array( array('text', 'login', array('Label'=>'Login :')), array('password','pass', array('Label'=>'Pwd :')), array('submit','envoyer', array('Label'=>'Login')), )); echo $form; 129 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Théorie de la configuration Beaucoup de méthodes de Zend_Form sont des set*() On peut aussi passer au contructeur des clés de tableau $form = new Zend_Form; $form->setAction('go/here/') ->setMethod(Zend_Form::METHOD_POST); // par défaut ->setEnctype(Zend_Form::ENCTYPE_URLENCODED) // par défaut ->setName('My form') ->setAttrib('id','AnaskaForm'); $form = new Zend_Form( array( 'action' =>'go/here/', 'method' => "post", 'name" => "My form', 'id' => 'AnaskaForm')); 130 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 131 Zend_Form_Element Ils constituent le coeur du formulaire, il faut les maitriser Ils étendent tous Zend_Form_Element et intègrent : Des décorateurs qui vont décrire comment rendre les éléments visuellement Des validateurs qui vont renseigner le formulaire de l'état de validation Des filtres qui vont filtrer la donnée que les éléments retournent Des chargeurs de classes permettant d'utiliser des classes personnalisées (PluginLoader) Un nom qui doit être unique parmis tous les éléments d'un form. Des messages d'erreurs utilisés par les validateurs Une description Un Label Une valeur : la valeur saisie par l'utilisateur Un indice de réquisition (champ obligatoire ou optionnel) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les Zend_Form_Element existants Zend_Form_Element_Captcha Zend_Form_Element_Checkbox (MultiCheckBox) Zend_Form_Element_File Zend_Form_Element_Hidden Zend_Form_Element_Hash Zend_Form_Element_Image Zend_Form_Element_Password Zend_Form_Element_Radio Zend_Form_Element_Reset Zend_Form_Element_Select (MultiSelect) Zend_Form_Element_Submit (Button) Zend_Form_Element_Text (TextArea) ... ... 132 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Options des éléments Les options se passent au constructeur : $element = new Zend_Form_Element_Text(array $options); ou en troisième argument de addElement() : $form->addElement('text', 'name', array $options); ou encore via des méthodes sur l'élément : $element = new Zend_Form_Element_Text('foo'); $element->setAttrib('foo','bar'); $element->setLabel('mylabel'); $element->setOrder(18); $element->setRequired(true); $element = new Zend_Form_Element_Text(array( 'name'=>'foo', 'foo'=>'bar', 'label'=>'mylabel', 'order'=>18, 'required'=>false)); 133 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Ajout d'éléments $form = new Zend_Form(); $form->addElement('text', 'login',array('Label'=>'Login :')); $form->addElement('password','pass',array('Label'=>'Pwd :')); ou $form = new Zend_Form(); $form->addElements(array( array('text', 'login',array('Label'=>'Login :')), array('password', 'pass',array('Label'=>'Pwd :')), ) ); ou $form = new Zend_Form(); $login = new Zend_Form_Element_Text(array('name'=>'login','Label'=>'Login :')); $form->addElement($login); // ... 134 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Ajout d'éléments avec Zend_Config form.elements.login.type = "text" form.elements.login.options.label = "Login :" form.elements.pass.type = "password" form.elements.pass.options.label = "Pwd :" form.elements.envoyer.type = "submit" form.elements.envoyer.options.label = "Login" form.action="go/here" form.method="post" $config = new Zend_Config_Ini('my/form.ini'); $form = new Zend_Form($config->form); $form->setView(new Zend_View); echo $form; 135 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Form exercice Créez un formulaire permettant de s'inscrire Voyez notre table"membres" pour la référence des champs Login - Password - Retapez le password - Email - Date de naissance - Ville Prévoyez 2 champs password (confirmation) Prévoyez un Captcha 136 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 137 Zend_Form : Récupération d'éléments $form = new Zend_Form(); $login = new Zend_Form_Element_Text(array('name'=>'login','Label'=>'Login :')); $form->addElement($login); // … $login = $form->getElement('login'); // … $login = $form->login; // la magie PHP // … $tousLesElements = $form->getElements(); //array formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Conception usuelle d'un formulaire On utilise rarement Zend_Form directement On préfère créer notre propre objet formulaire On n'appelle pas le constructeur La méthode init() a été prévue pour la création du formulaire class Form_Login extends Zend_Form { public function init() { $this->addElements(array( array('text', 'login',array('Label'=>'Login :')), array('password', 'pass',array('Label'=>'Pwd :')), )); $this->setAction('/go/here/'); } } $form = new Form_Login; $form->setView(new Zend_View); echo $form; 138 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 139 Zend_Form exercice Refactorisez votre formulaire pour encapsuler sa création dans une classe à part formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Valider le formulaire 140 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Auto-validation du formulaire isValid() : Distribue le tableau qu'on lui passe à ses éléments (il se sert des clés) Chaque élément s'affecte la valeur qui le concerne Demande aux éléments de se valider Ils demandent à leurs validateurs de les valider Retourne le résultat de la validation (bool) Ceci constitue la vraie puissance de Zend_Form $form = new Zend_Form($configArray); $form->setView(new Zend_View); if ($_SERVER['REQUEST_METHOD'] == "POST") { if ($form->isValid($_POST)) { $form = 'validé !'; } } echo $form; 141 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 142 Valider le formulaire Valider le formulaire revient à demander à chaque élément d'exécuter chaque validateur, qu'on lui aura ajouté, sur sa valeur filtrée (celle saisie) Attention aux effets de bord, les filtres passent avant ! Dire à un élément setRequired(true) à pour effet d'ajouter un validateur "NotEmpty" à l'élément Si un validateur échoue, il enregistre un message d'erreur dans l'élément sur lequel il fait effet Aussi, Zend_Form est informé qu'il n'est pas valide car un de ses éléments possède une erreur Le décorateur "Errors" se chargera d'afficher les erreurs formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Valider le formulaire : exemple login Zend_Validate_* et Zend_Filter_* sont utilisés Elément "Login" : Cet élément est simplement requis (doit être non vide) $form->addElement('text, 'login', array('Label'=>'Login :', 'required'=>true,) ); 143 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 144 Valider le formulaire : exemple password Elément "Password" : L'élément est requis (valeur non vide obligatoire) Un alphanumérique est requis 6 caractères minimum $form->addElement('password', 'pass', array('Label'=>'Pwd :', 'required'=>true, 'validators'=>array( array('validator'=>'stringlength', 'options'=>array('min'=>6)), 'Alnum', ) )); formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 145 Valider le formulaire : exemple password On peut utiliser les objets validateurs aussi, ainsi que les méthodes explicites : $form->addElement('password', 'pass', array('Label'=>'Pwd :', 'required'=>true, 'validators'=>array( array('validator'=>'stringlength', 'options'=>array('min'=>6), true), 'Alnum' ) )); $pass = $form->getElement('pass'); $pass->addValidators(array( array(new Zend_Validate_StringLength(6), true), new Zend_Validate_Alnum() )); formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 146 Valider le formulaire avec Zend_Config Zend_Config possède une méthode toArray() Comme nous l'avons vu, il suffit que celle-ci retourne le tableau que les méthodes de Zend_Form accepte "a+1 = b donc a = b-1" on retombe sur nos pattes form.elements.login.type = "text" form.elements.login.options.label = "Login :" form.elements.login.options.required = "true" form.elements.pass.type = "password" form.elements.pass.options.label = "Pwd :" form.elements.login.options.required = "true" form.elements.login.options.validators.alnum.validator = "alnum" form.elements.login.options.validators.longueur.validator = "stringlength" form.elements.login.options.validators.longueur.options.min = 6 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 147 Validation : afficher les erreurs On peut automatiser via des décorateurs ("Errors") C'est fastidieux, vos formulaires comportent beaucoup de cas particuliers Mais ça reste possible de le factoriser Affichons les erreurs simplement dans le template <table> <tr> <td><?php echo $this->element->no;?></td> <td><?php echo implode('-',$this->element->no->getMessages());?></td> </tr> <tr> <td><?php echo $this->element->type_ta_grp;?></td> <td><?php echo implode('-',$this->element->type_ta->getMessages());?></td> </tr> <tr> <td colspan="2"><?php echo $this->element->envoyer;?></td> </tr> </table> formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 148 Créer son validateur Etendez Zend_Validate_Abstract Chaque validateur reçoit toutes les variables dans $context class Anaska_Validate_PasswordConfirmation extends Zend_Validate_Abstract { const NOT_MATCH = 'notMatch'; protected $_messageTemplates = array( self::NOT_MATCH => 'Les 2 mots de passes ne correspondent pas'); public function isValid($value, $context = null) { $value = (string) $value; $this->_setValue($value); if (is_array($context)) { if (isset($context['password_confirm']) && ($value == $context['password_confirm'])) { return true; } } elseif (is_string($context) && ($value == $context)) { return true; } $this->_error(self::NOT_MATCH); return false; } } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Valider le formulaire : exercice Ajoutez de la validation et des filtres au formulaire Vérifiez que tout fonctionne correctement 149 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 150 Récupérer les valeurs Pour récupérer les valeurs, utilisez getValue('champ') ou getValues() if ($form->isValid($_POST)) { echo $form->getValue('login'); } N'utilisez jamais la source de données directement ($_POST par ex) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Traduction du formulaire Grâce à Zend_Translate, vous pouvez traduire Les labels Les messages d'erreurs des validateurs Les légendes et descriptions Les valeurs dans les "select" Créez un objet Zend_Translate Ajoutez le au formulaire (directement ou via le registre) C'est fini : tout ce qui trouve une traduction sera alors automatiquement traduit dans la locale du visiteur 151 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Décorons nos formulaires 152 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 153 Décorons nos formulaires Chaque élément possède des objets Zend_Form_Decorator Ils sont chargés de représenter leur contenu, généralement grâce à des tags HTML Le CSS permet aussi beaucoup de choses Les décorateurs par défaut proposent des "id" ou des "class" formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 154 Les différents décorateurs Callback: utilise une callback PHP pour trouver le rendu Description: rend l'attribut 'description' de l'élément DtDdWrapper: contenu dans un <dd> précédé d'un <dt> vide Errors: rend les messages d'erreurs dans des <ul><li> Fieldset: rend dans un fieldset avec légende éventuelle FormElements: retourne le rendu de tous les éléments et sous-formulaires en leur partageant l'objet de vue et de traduction Form: décore avec un <form> HtmlTag: met le contenu entre deux tags HTML identiques, ou alors met un tag avant ou après le contenu (sans l'entourer donc) Image: rend une image Label: rend le label d'un élément avant celui-ci (devant) (...) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 155 Les décorateurs (défaut) des éléments Par défaut, il se passe ceci : $elements->addDecorators(array( array('ViewHelper'), array('Errors'), array('Description', array('tag' => 'p', 'class' => 'description')), array('HtmlTag', array('tag' => 'dd')), array('Label', array('tag' => 'dt')), )); 5 décorateurs sont chargés. Le premier (haut de pile) rend son contenu ... Le deuxième rend son contenu à la suite, avant, autour ou à la place du contenu du décorateur précédant Etc... formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 156 Les décorateurs : la technique Design pattern Decorateur Composite : $label->render( $htmlTag->render( $description->render( $errors->render( $viewHelper->render(''))))); Le rendu de 1 se fait à la place de rien du tout : c'est le rendu originel Le rendu de 2 se fait autour, avant, après ou à la place du rendu de 1 Rendu de 3 lui-même fait autour, avant après ou à la place du rendu de 2 .... formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les décorateurs : la technique ViewHelper Errors (ul li par défaut) HtmlTag (dd par défaut) Label (dt par défaut) <input name="foo" id="foo" type="text" value="" /> <input name="foo" id="foo" type="text" value="" /> <div class="error"><ul> <li>...</li> </ul></div> <dd> <input name="foo" id="foo" type="text" value="" /> <div class="error"><ul> <li>...</li> </ul></div> </dd> <dt><label for="foo" class="optional">Foo</label><dt> <dd> <input name="foo" id="foo" type="text" value="" /> <div class="error"><ul> <li>...</li> </ul></div> </dd> 157 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les décorateurs du formulaire On sait présenter (rendre) des éléments, mais et le formulaire? Il possède aussi des décorateurs Qui vont rendre ses éléments, autour d'autres décorateurs ! $form->setDecorators(array( 'FormElements', // contenu des éléments rendus, partage de la vue array('HtmlTag', array('tag' => 'dl')), // un tag 'Form' // une balise form )); <form action="/form/action" method="post"> <dl> {rendu des éléments} </dl> </form> FormElements : Décorateur qui rend les décorateurs des éléments Form : Décorateur qui rend la balise <form> 158 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Gestion des décorateurs Enlever un décorateur $element->removeDecorator('label'); Si on ajoute un décorateur, il sera mis à la suite de la pile Le mieux est de les spécifier tous en une fois Exemple pour un rendu en tableau HTML $element->setDecorators(array( 'ViewHelper', 'Errors', array( array('1st'=>'HtmlTag'),array('tag'=>'td') ), array('Label',array('tag'=>'td')), array( array('2nd'=>'HtmlTag'),array('tag'=>'tr') ) )); 159 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Décoration manuelle Vous pouvez aussi invoquer "echo" sur des éléments un à un : <?php echo $form->login; echo "<br />"; echo $form->pass; echo $form->foobar; ?> <br /> <?php echo $form->envoyer; ?> Chaque élément est un attribut virtuel du formulaire On appelle echo sur les éléments du formulaire Qui se rendent alors via leurs décorateurs respectifs Et on place (sépare) ces éléments comme on le souhaite 160 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 161 Réutilisation : grouper les éléments (2) Class Anaska_Form extends Zend_Form { public function addTextButtonElement($name, array $options = null) { $this->addElement('text', $name, $options); $btnOptions = array('Label'=>'...'); if (isset($options['btnUrl'])) { $btnOptions['onclick'] = "javascript:window.open(\"{$options['btnUrl']}\");"; } $this->addElement('button',$name.'_btn',$btnOptions); $this->addDisplayGroup( array($name, $name.'_btn'), $name.'_grp', array( 'disableLoadDefaultDecorators' => true, 'decorators' => array('FormElements'), ) ); } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 162 Réutilisation : grouper les éléments (3) Fichier PHP : //PHP $form->addTextButtonElement('groupe_exemple', array('Label'=>'exemple de groupe', 'btnUrl'=>'click.html', 'required'=>true, )); Affichage HTML : echo $form->groupe_exemple_grp formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 163 Structure des décorateurs Les décorateurs sont des Zend_Form_Decorator_* Ils héritent tous de Zend_Form_Decorator_Abstract Dont voici les options : Placement : l'endroit ou le décorateur place son contenu par rapport au contenu qu'il a recu Separator : le séparateur de contenus ("\n" par défaut) Après, chaque décorateur a des options qui lui sont propres : HtmlTag (tag) Label (tag, class) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Changer/Configurer les décorateurs Ajout via l'élément, individuellement : $element->addDecorator(new Zend_Form_Decorator_HtmlTag(array('tag'=>'p'))); Ajout via l'élément, individuellement lors de son insertion dans le formulaire : $form->addElement('text', 'foo', array('decorators' => array('ViewScript, 'HtmlTag')); Modification via l'élement : $element->getDecorator('Label')->setOption('tag', 'p'); Ajoutclass via My_Form le formulaire global, pour tous les éléments : extends Zend_Form { protected $_elementDecorators = array('ViewHelper', 'Label', 'HtmlTag'); public function init() { ... } } 164 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Form décorateurs : exercice Les 2 champs mot de passe doivent être collés sur la même ligne Les noms des éléments (labels) doivent apparaître en gras 165 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Mini-application MVC La partie gauche fait apparaître un formulaire qui change lorsqu'on est connecté : c'est un lien vers la déconnexion Créez le formulaire et gérez l'authentification en session Le temps de vie du login doit être configurable 166 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 167 Mini-application MVC, refactoring LA règle maitresse Donnez de la puissance à vos modèles, et raccourcissez au maximum le code de vos contrôleurs Le contrôleur n'est pas un "fourre-tout" Chaque action doit faire 20 lignes maximum C'est très classique chez les développeurs PHP qui ne sont pas habitués à penser MVC que de créer des "FSUC" (Fat Stupid Ugly Controller) MVC, c'est avant toute chose une organisation stricte, précise et minimaliste du code, chaque ligne est aussi importante que sa voisine formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 168 Un contrôleur... D'après vous, quelles sont les responsabilités qu'un contrôleur n'a pas à prendre ? Au contraire, quelles sont les tâches qu'il devra gérer (au moyen d'autres objets éventuellement) ? formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 169 Mini-application MVC, couche de services Class IndexController extends Anaska_Controller_Action { public function indexAction() { $this->view->nbreMembres = Service_Membres ::totalCount(); $this->view->nbreEmprunts = Service_Emprunts ::totalCount(); $lastEmprunt = Service_Emprunts ::findLast(); $this->view->empruntRecent = $lastEmprunt['titre']; $this->view->emprunteurRecent = $lastEmprunt['nom']; } } Si vous pensez mettre la main sur une fonctionnalité que tous vos contrôleurs vont utiliser, créez votre propre classe de gestion des contrôleurs (ici Anaska_Controller_Action) Sinon, utilisez une aide d'action Vos contrôleurs doivent consommer une couche de services, c'est le point d'entrée vers le modèle formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 170 Mini-application MVC, refactoring Comment gérez-vous vos formulaires ? Comment gérez-vous vos modèles ? La plupart du temps, c'est le modèle qui donne naissance au formulaire, et le modèle est validable, au moyen de son formulaire Zend_Db_Table_* proposent des fonctionnalités assez sommaires Mais comme d'habitude : ils proposent des possibilités de personnalisation très intéressantes Redéfinissez les Zend_Db_Table_Row pour créer vos propres conteneurs Redéfinissez Zend_Db_Table_Abstract pour un couplage adapté entre les passerelles et les objets métiers Il est aussi possible de rajouter une couche de cache, grâce à Zend_Cache formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 171 Mini-application MVC, refactoring class Membres extends Anaska_Db_Table_Row_Abstract { public function getForm($type = null) { $form = $this->getTable()->getForm($type); $primary = $this->getTable()->info('primary'); $primary = $primary[1]; if ($this->_data[$primary] != null) { $form->populate($this->_data); } return $form; } public function save() { $form = $this->getForm(); if (!$form->isValid($this->_data)) { return false; } return parent::save(); } class AccountController extends Anaska_Controller_Action { public function registerAction() { $form = $this->membres->getForm('register'); if ($this->getRequest()->isPost()) { $post = $this->_request->getPost(); $row = $this->membres->createRow($post); if ($row->save() !== false) { $this->view->form = "Validé"; } } $this->view->form = $form; } } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 172 Mini-application MVC, autorisations Refactoriser, c'est remanier le code de l'intérieur, sans que ça ne se voit à l'extérieur Souvent, on "casse" quand même l'API En fait, il faut toujours penser vers l'infini, et vers le futur Mes livres sont ajoutables, et éditables Seront-ils les seuls dans ce cas là ? Il va devenir interdit d'accéder à la page "mes emprunts' si je ne suis pas identifié Sera-ce la seule page sur laquelle il y aura une interdiction ? Zend Framework n'impose rien, il propose une structure extrêmement maniable, à vous de profiter de cet énorme avantage ! formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 173 Mini-application MVC, authentification Vous avez crée un formulaire d'authentification pour donner une identité à un membre Comment avez-vous fait ? N'oubliez pas que le contrôleur n'a pas à effectuer l'authentification class MembreController extends Zend_Controller_Action { public function loginAction() { $form = Service_Membres::getForm('login') ; If ($this->_request->isPost()) { If (Service_Membres::authenticate($_POST)) { $this->_redirect('/') ; } } $this->view->loginForm = $form ; } } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 174 Mini-application MVC, un petit point Vous savez ce que vous voulez, car vous avez un cahier des charges, et une expression (précise) du besoin Pensez objet, pensez couplage, pensez responsabilité Architecture logicielle Je conçois des plans avant de bâtir mon application Pensez réutilisabilité Quelles sont les parties communes dans mon code ? Comment faire en sorte qu'un changement dans le programme ne puisse être effectué que dans un seul fichier, et pas 80 ? Le plus bel exemple de réutilisabilité est le ZendFramework lui-même N'hésitez jamais à analyser sa source avec le déboggeur par exemple formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 175 Mini-application MVC, autorisations Regardez la table "membres", elle possède une colonne "rôle" Les libraires ont le droit d'ajouter des livres Les admins ont tous les droits Les personnes sans rôle dans la base ont des droits minimaux Implémentez une gestion des ACLs Pensez pour le futur : demain, il y a 40.000 rôles différents, et 250 contrôleurs, il est hors de question de dupliquer du code ... formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 176 Formation Zend Framework architecte A: Rappels sur le ZF 1. Les différents packages 2. Le niveau de couplage 3. Les versions et l'évolution du framework 4. Le futur de Zend framework B: Comprendre et maitriser MVC 5. Monter une application MVC 6. Gérer des bases de données 7. Monter un modèle 8. Formulaires, Authentification 9. Application et bootstrap 10. Pattern contrôleur frontal 11. Objets de requête et réponse 12. Routage 13. Vues, templates et Layouts 14. Plugins MVC et aides d'action 15. Aides de vues C: Ajax 16. Introduction à JQuery 17. ZendFramework et Ajax 18. Intégration dans les vues et les layouts D: Gérer la redondance des developpements 19. Génie logiciel, design patterns et UML 20. Couplage, cohésion et responsabilités 21. Utiliser le débogueur pour comprendre le code 22. Créer son propre framework sur ZendFramework E. Testabilité 23. Rappels sur PHPUnit 24. Ecrire et automatiser le lancement des tests 25. Zend_Test et tests fonctionnels 26. Assertions sur le DOM F: Conclusions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Ajax avec JQuery Jquery est un framework Ajax (Javascript) moderne Il se décompose en 2 parties : Jquery "Core" : http://jquery.com Les bases du framework JqueryUI : http://jqueryui.com/ Les fonctionnalités avancées et les thèmes graphiques Les 2 sont nécessaires pour profiter de toutes les fonctionnalités Vous pouvez fabriquer votre propre bibliothèque sur mesure Nous placerons les javascripts dans le dossier public/scripts 177 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr JQuery et ZendX_JQuery ZendX_JQuery est un composant qui va piloter JQuery : Simplifie la création des balises <script> Gère les dépendances et les éventuels conflits Ajoute JQuery et UI dans les balises <script> Ajoute les fonctions de démarrage dans les balises <script> document.ready(function() { .... 178 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 179 ZendX_JQuery : fonctionnement Pour activer toutes les fonctions, il faut activer ZendX_JQuery dans notre vue MVC : ZendX_JQuery::enableView($view); Les vues vont dès lors pouvoir utiliser les helpers JQuery : echo $this->autocomplete(...) Le Layout, rendu après les vues, va alors demander à ZendX_JQuery d'écrire le javascript nécessaire dans les balises <script>, en fonction des utilisations qui en ont été faites dans la vue auparavant echo $this->jQuery(); formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 180 ZendX_JQuery : Aide de vue JQuery echo $this->jQuery(); Afficher l'aide JQuery, c'est afficher tout ce que les autres aides de vues utilisées avant ont enregistré dans l'emplacement (ZendX_JQuery_View_Helper_JQuery_Container) L'aide JQuery va alors faire en sorte que la librairie JQuery nécessaire soit incluse depuis les CDNs de Google. <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.5.2/jquery-ui.min.js"></script> Mais vous pouvez commander l'aide JQuery, et changer des paramètres formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 181 Possibilités de l'aide de vue JQuery $this->jQuery()->addStylesheet('/styles/ui.css'); $this->jQuery()->setLocalPath('/scripts/jquery-1.3.2.min.js'); $this->jQuery()->setUiLocalPath('/scripts/jquery-ui-1.7.1.custom.min.js'); $this->jQuery()->addJavascriptFile('/scripts/autocomplete.js'); Les feuilles de styles sont disponibles sur http://jqueryui.com Elles changent donc le "thème" des composants JQuery affichés Vous pouvez aussi éviter le CDN, en indiquant les chemins vers vos propres librairies setLocalPath(path/to/JQueryCore) setUiLocalPath(path/to/JQueryUI) Ajout de bibliothèques supplémentaires : addJavascriptFile() formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les diverses aides de vues JQuery <form method="post" action="/hello/world"> Date: <?php echo $this->datePicker("champ_date", '', array('defaultDate' =>date('Y/m/d', time()))); ?> <?php echo $this->autoComplete("ville", "Indiquez votre ville", array('url' => 'login/autocomplete', 'multiple' => true,)); ?> </form> <div id="container"> </div> <?php echo $this->ajaxLink("Afficher la liste des livres", "livres/liste/?format=xml", array('update' => '#container', 'beforeSend'=>'hide', 'complete'=>'show')); $this->helper($id, $value, $params, $attribs) 182 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 183 JQuery : conclusions La documentation officielle donne la liste de toutes les aides http://framework.zend.com/manual/fr/zendx.jquery.view.html Pour une personnalisation extrême, il faut lire la documentation de JQuery Quoiqu'il arrive, vous n'écrivez pas de javascript (ou très peu) Vous passez des paramètres aux aides de vue Elles écrivent le javascript qu'il faut Vous pouvez créer vos propres aides de vue formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 184 Formation Zend Framework architecte A: Rappels sur le ZF 1. Les différents packages 2. Le niveau de couplage 3. Les versions et l'évolution du framework 4. Le futur de Zend framework B: Comprendre et maitriser MVC 5. Monter une application MVC 6. Gérer des bases de données 7. Monter un modèle 8. Formulaires, Authentification 9. Application et bootstrap 10. Pattern contrôleur frontal 11. Objets de requête et réponse 12. Routage 13. Vues, templates et Layouts 14. Plugins MVC et aides d'action 15. Aides de vues C: Ajax 16. Introduction à JQuery 17. ZendFramework et Ajax 18. Intégration dans les vues et les layouts D: Gérer la redondance des developpements 19. Génie logiciel, design patterns et UML 20. Couplage, cohésion et responsabilités 21. Utiliser le débogueur pour comprendre le code 22. Créer son propre framework sur ZendFramework E. Testabilité 23. Rappels sur PHPUnit 24. Ecrire et automatiser le lancement des tests 25. Zend_Test et tests fonctionnels 26. Assertions sur le DOM F: Conclusions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Les tests unitaires et fonctionnels 185 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Qu'est-ce ? Testez vous vos programmes ? Possédez vous un pôle qualité ? Un code fouilli est difficilement testable Un code maintenable est testable Pour écrire un code maintenable, écrivez des tests Tester son code Permet d'éviter la peur du changement Permet de valider le bon fonctionnement d'un algorithme Participe à l'analyse de la qualité du projet 186 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Un code difficilement testable ... Complexité cyclomatique Nombre de points de décisions, de divergences If – while – switch/case ... Chaque point de décision doit faire correspondre un cas de test Couverture de tests Est ce que chaque ligne du programme est testée ? Plus il y a de branches, plus c'est difficile à vérifier 187 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 188 Testabilité switch ($forme) { case ‘cercle’: $aire = PI * $rayon * $rayon; break; case ‘rectangle’: $aire = $largeur * $longeur; break; } 1 seule implémentation Objets testables unitairement Classe mère testable 2 branches de code Sur 1 paramètre d'entrée, plusieurs algorithmes très différents peuvent intervenir. class Cercle extends Forme{ function aire() { return PI * pow($this->rayon,2); } } class Rectangle extends Forme { function aire() { return $this->larg * $this->haut; } } formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 189 Tester ses algorithmes $a = array(); $a[] = 'element'; Test automatisé echo count($a); Test manuel classique echo count($a) == 1 ? 'ok' : 'ko'; assertTrue(count($a) == 1); Test automatisé factorisé Réutilisable function assertTrue($cond) { if (!$cond) { throw new Exception('Echec'); } } Lorsque vous êtes tentés d'utiliser une commande print ou une expression de debug pour écrire quelque chose, écrivez plutôt un test. formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 190 Pourquoi tester ? Sur un projet, plus le temps passe, plus : Les spécifications changent Le code doit être remanié Des ajouts doivent être faits L'application gonfle et s'enrichit Se complexifie Les bugs apparaissent Le temps passé à débugguer augmente de manière significative Si on avait pris le temps d'écrire des tests, le temps de débuggage aurait été beaucoup plus court Ecrire des tests prend du temps : c'est souvent un gain de temps formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 191 Pourquoi tester ? Les tests offrent de nombreux avantages : Fournir à l'auteur du code et aux lecteurs la certitude que les corrections produisent bien l'effet recherché. Permet aux développeurs de découvrir les effets de bord du système. Très bon outil pour mettre immédiatement en avant les régressions, et pour s'assurer que la même régression ne se reproduira pas. Illustrent de façon concrète les modes d'utilisation de l'API et contribuent de façon significative aux efforts de documentation. formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Qui teste ? L'industrie informatique Les tests font partie de la qualité Mais ne représente pas 'LA' qualité Le monde du logiciel Le monde du jeuvidéo Le monde de l'embarqué Des centaines, des milliers de procédures de tests, lancées automatiquement Pourquoi le monde du web ne testerait-il pas ?? 192 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Outil de test L'outil de test est une solution complète de tests Simple à apprendre Tests simples à écrire Simples et rapide à exécuter Tests isolés les uns des autres Suites de tests SimpleTest Plus maintenu, compatibilité PHP5 bancale PHPUnit La référence : très complet, très utilisé Même principe que JUnit 193 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr TDD : Test Driven Developpement Faire ressortir les fonctionnalités dont le logiciel a réellement besoin Ne pas laisser le développeur imaginer ce qui pourrait être utile. Ecrire des tests simples AVANT tout autre code Constater que les tests échouent Ecrire le code de manière simpliste Constater que les tests passent Repérer les doublons Factoriser Vérifier que les tests passent toujours 194 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr PHPUnit : généralités Outils en lignes de commandes S'installe via PEAR Possède des caractéristiques avancées si relié à l'extension PHP Xdebug Fonctionnalités : Tests unitaires TDD BDD : Behavior Driven Developpement Gestion des bases de données Déguisements d'objets (Mocks, Stubs) Tests d'intégration ( en duo avec Selenium Server) Tests de performance Intégration dans des outils d'analyse de qualité (PHPUnderControl) 195 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Exercice PHPUnit : installons-le Installez les paquets "php-pear" et "php5-dev" Mettez à jour pear si nécéssaire Installez PHPUnit Installez XDebug (optionnel mais recommandé) >aptitude install php-pear php5-dev >pecl install xdebug >pear upgrade-all >pear channel-discover pear.phpunit.de >pear channel-discover pear.symfony-project.com >pear install phpunit/PHPUnit >phpunit Regardez toutes les options offertes par PHPUnit Utilisation : >phpunit fichier_de_tests.php 196 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr PHPUnit : Options de lancement PHPUnit 3.5.9 by Sebastian Bergmann. --log-junit <file> --log-tap <file> --log-dbus --log-json <file> Log test execution in JUnit XML format to file. Log test execution in TAP format to file. Log test execution to DBUS. Log test execution in JSON format. --coverage-html <dir> Generate code coverage report in HTML format. --coverage-clover <file> Write code coverage data in Clover XML format. --testdox-html <file> Write agile documentation in HTML format to file. --testdox-text <file> Write agile documentation in Text format to file. --filter <pattern> Filter which tests to run. --group ... Only runs tests from the specified group(s). --exclude-group ... Exclude tests from the specified group(s). --list-groups List available test groups. --loader <loader> --repeat <times> --tap --testdox --colors --stderr --stop-on-error ... TestSuiteLoader implementation to use. Runs the test(s) repeatedly. Report test execution progress in TAP format. Report test execution progress in TestDox format. Use colors in output. Write to STDERR instead of STDOUT. Stop execution upon first error. 197 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr PHPUnit : Conseils PHPUnit est une trousse à outils qui évolue Maintenez le à jour (améliorations régulières) Veillez Lisez le manuel officiel (très bien écrit) Possédez une version de PHP récente PHPUnit tire partie des avantages des toutes dernières versions de PHP C'est le cas notamment pour PHP5.3 Installez l'extension Xdebug Elle rajoute des possibilités très utiles à PHPUnit 198 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 199 PHPUnit : écrire des tests Classe nom-de-la-classe-testeeTest étend PHPUnit_Framework_TestCase Ceci représente un "scénario de test" (un ensemble de tests) D'autres classes à étendre possibles, pour rajouter des foncionnalités Tous les tests sont des méthodes publiques, qui commencent par le mot-clé 'test' Elles doivent avoir un nom très explicite public function testViewRendererShouldThrowExceptionWhileNotInitialized() La méthode setUp() est le constructeur de tests, elle est appelée avant chaque test (isolation du contexte) La méthode tearDown() est le destructeur de tests, elle est appelée après chaque test (isolation du contexte) formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr PHPUnit : exemple et vocabulaire Scénario cas de test assertion class ArrayTest extends PHPUnit_Framework_TestCase { protected $_arrayToTest; protected function setUp() { $this->_arrayToTest = array(); } public function testNouveauTableauEstVide() { // Vérification que le nombre d'éléments dans la fixture Array est 0. $this->assertEquals(0, sizeof($this->_arrayToTest)); } public function testTableauContientUnElement() { // Ajout d'un élément à la fixture Array $this->_arrayToTest[] = 'Element'; } } ?> // Vérification que le nombre d'éléments dans la fixture Array est 1. $this->assertEquals(1, sizeof($this->_arrayToTest)); 200 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 201 PHPUnit : résultats julien@julien:/tests$ phpunit CalculTest.php PHPUnit 3.5.9 by Sebastian Bergmann. EFI. Time: 0 seconds, Memory: 4.50Mb There was 1 error: 1) CalculTest::testAdd Undefined variable: c /media/www/labo/astellia/tdd/library/Calculette.php:8 /media/www/labo/astellia/tdd/tests/CalculTest.php:15 -There was 1 failure: 1) CalculTest::testDiv Failed asserting that <integer:15> matches expected <integer:10>. /media/www/labo/astellia/tdd/tests/CalculTest.php:22 FAILURES! Tests: 4, Assertions: 4, Failures: 1, Errors: 1, Incomplete: 1. . Pass F Fail E Erreur PHP I Incomplet S Skipped formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr PHPUnit : assertions Les assertions fonctionnent globalement toutes sur le même principe $this->assert*($expectedVal, $actualVal, $errorMessagePerso); Beaucoup d'assertions ! http://www.phpunit.de/manual/3.5/en/api.html#api.assert Les exceptions se testent avec setExpectedException() public function testEnvoiException() { $this->setExpectedException('Foo', 'bar'); // ce test doit envoyer une exception Foo qui contient 'bar' dans son message pour passer, sinon échec } Les erreurs PHP (non fatales) sont interceptées par PHPUnit et traitées commes des exceptions de la classe PHPUnit_Framework_Error 202 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr System Under Test (SUT) Le SUT est le système testé Les préconditions sont l'état dans lequel doit se trouver le SUT avant tout test (assertPreconditions()) Les postconditions sont l'état dans lequel doit se trouver le SUT après tout test (assertPostConditions()) Les invariants sont les conditions nécessaires pour que le SUT puisse être testé SetUp() charge l'environnement du SUT tearDown() détruit l'environnement du SUT Le contexte entre chaque test est totallement isolé 203 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 204 PHPUnit : tests à l'isolement PHPUnit isole le contexte de vos tests de manière à ce qu'ils ne se marchent pas dessus setUp() est appelée avant chaque test tearDown() est appelée après chaque test assertPreConditions() est appelé après le setUp() assertPostConditions() est appelé avant le tearDown() setUpBeforeClass() est appelée avant chaque scénario de tests tearDownAfterClass() est appelée après chaque scénario de tests Toute modification sur une superglobale ne sera pas reflétée d'un test à l'autre (--noglobals-backup) En revanche, le contexte statique des classes n'est pas traité Sauf sous PHP5.3 et --static-backup formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Couverture de code Il faut vérifier qu'un maximum de code est couvert par les tests : Ecrire des lignes courtes, peu d'instructions par ligne (Pas de if-then-else courts) Utiliser Xdebug avec PHPunit et l'option –report Permet de vérifier le code mort Permet de vérifier le code non testé Dans lequel des bugs peuvent survenir 205 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Couverture de code 206 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Apprenez des autres Comme d'habitude : analysez les tests de ZendFramework Dossier "tests" de l'archive des sources Vous pouvez aussi les lancer pour tester le framework dans un cadre spécifique (plateforme) Vous trouverez de bonnes idées dans les sources 207 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 208 Zend_Test Zend_Test propose des outils permettant de créer des tests d'intégration De tester ses contrôleurs, et le bon enchainement des actions sur l'application Bâti par dessus PHPUnit_Framework_TestCa se Rajoute des assertions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Test : théorie 209 La propriété $bootstrap de la classe doit permettre de configurer le fichier d'amorçage. C'est soit : Un fichier, qui sera alors lu Une fonction Une méthode d'une classe class UserControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { public function setUp() { $this->bootstrap = array($this, 'bootstrap'); // première possibilité $this->bootstrap = 'path/to/my/bootstrap.php'; // deuxième possibilité parent::setUp(); } } Le bootstrap doit configurer les objets, mais ne DOIT PAS lancer le dispatch formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Test et contexte CLI Attention, PHPUnit fonctionne en mode CLI Pas de $_SERVER Pas de session Zend_Session possède un drapeau $_unitTestEnabled Les objets de requêtes et réponse ne sont pas interchangeables Zend_Controller_Request_HttpTestCase Zend_Controller_Response_HttpTestCase Ces objets gèrent l'absence de contexte HTTP Vous pouvez les récupérer, les modifier, mais pas les changer 210 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Zend_Test : exemple class IndexControllerTest extends Zend_Test_PHPUnit_ControllerTestCase { protected function setUp() { $this->bootstrap = dirname(__FILE__) . '/bootstrapTest.php'; parent::setUp (); } public function testIndexAction() { $this->dispatch ( '/index/index' ); $this->assertController ( 'index' ); $this->assertAction ( 'index' ); } } Le bootstrapTest est preque le même que le vrai bootstrap 211 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 212 Zend_Test : Quelques règles Désactivez les caches Zend_Cache : souvent ils introduisent des effets de bords très difficiles à détecter Ne faites aucun appels à $_SERVER, cette variable est très différente en environnement CLI Mettez Zend_Session::$_unitTestEnabled = true (automatique) Au début, ne soyez pas trop gourmands, écrivez les tests uns à uns, pas plusieurs d'un coup formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 213 Zend_Test : autre exemple Tester que l'affichage de la page de la liste des livres est interdit public function testAffichePageLivreKoSiNonLoggue() { Acl_MyAcl::getInstance()->deny('guest', 'livres', 'liste'); $this->dispatch ('/livres/liste' ); $this->assertController('error'); $this->assertTrue($this->getResponse()->isException()); $this->assertResponseCode(403); } Dans le même registre : Testez que si la personne est logguée, l'affichage de la liste est autorisé En utilisant les assertion DOM ou Xpath, vérifiez la présence du formulaire sur la page d'accueil si on est pas encore loggué formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 214 Formation Zend Framework architecte A: Rappels sur le ZF 1. Les différents packages 2. Le niveau de couplage 3. Les versions et l'évolution du framework 4. Le futur de Zend framework B: Comprendre et maitriser MVC 5. Monter une application MVC 6. Gérer des bases de données 7. Monter un modèle 8. Formulaires, Authentification 9. Application et bootstrap 10. Pattern contrôleur frontal 11. Objets de requête et réponse 12. Routage 13. Vues, templates et Layouts 14. Plugins MVC et aides d'action 15. Aides de vues C: Ajax 16. Introduction à JQuery 17. ZendFramework et Ajax 18. Intégration dans les vues et les layouts D: Gérer la redondance des developpements 19. Génie logiciel, design patterns et UML 20. Couplage, cohésion et responsabilités 21. Utiliser le débogueur pour comprendre le code 22. Créer son propre framework sur ZendFramework E. Testabilité 23. Rappels sur PHPUnit 24. Ecrire et automatiser le lancement des tests 25. Zend_Test et tests fonctionnels 26. Assertions sur le DOM F: Conclusions formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 215 Zend Framework, conclusions : Zend Framework est un socle sûr et stable pour vos projets, supporté par Zend Son design architectural fait qu'il est très facilement étendable, personnalisable Sa source est disponible, analysable Il vous propose de ''bien'' programmer et de tirer partie des avantages incontournables de la POO (de PHP5) en entreprise : A votre rythme Travail en équipe facilité, à tous niveaux Socle commun – procédure commune - programmes testés formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr 216 Zend Framework, conclusions : ZendFramework impose néanmoins d'avoir des compétences poussées en PHP5 et en Orientation Objets Le problème auquel vous faites face a surement déjà été résolu Zend Framework répond à 85% des besoins d'un développement PHP en entreprise Ne cherchez pas à réinventer la roue ! Maitriser Zend Framework aujourd’hui c’est assurer une pérennité pour les applications webs d’aujourd’hui, mais aussi de demain formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Aide et Documentation Vous trouverez une mine d’informations sur le site web http://framework.zend.com Une liste des Buts & Bénéfices des Composants Un Guide de Référence pour le Programmeur , une API Quelques sites intéressants : http://devzone.zend.com http://zend-framework.developpez.com/ http://www.z-f.fr http://weierophinney.net/matthew/ http://ralphschindler.com/ http://blog.astrumfutura.com http://www.thomasweidner.com/ http://blog.lyrixx.info/ http://akrabat.com/ 217 formation Zend Framework architecte | AlterWay | http://www.alterwayformation.fr Questions ? Contact : [email protected] Page : http://julien-pauli.developpez.com Blog : http://blog.developpez.com/julienpauli Ouvrage : Zend Framework, bien développer en PHP 218
Documents pareils
Développement d`un moteur de recherche avec Zend Search
• Cf. http://framework.zend.com/manual/fr/zend.search.lucene.searching.html et
http://framework.zend.com/manual/fr/zend.search.lucene.query-language.html .