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

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 .

Plus en détail