Le point de départ est le suivant : si on veut enrichir la vue avec des méthodes utiles pour tout le site, comme la mise en forme d’une date, ou d’un montant monétaire, la solution natur
Trang 1On peut gérer le layout au niveau de chaque action, soit pour modifier le
docu-ment utilisé avec l’instruction
/ / U t i l i s e r a u t r e p h t m l comme l a y o u t
$ t h i s−>_helper −>l a y o u t ( )−>s e t L a y o u t ( ’ a u t r e ’ ) ;
soit en n’utilisant plus du tout le layout, par exemple pour produire un document non écrit en HTML
/ / Ne p a s u t i l i s e r l e l a y o u t
$ t h i s−>_helper −>l a y o u t ( )−>d i s a b l e L a y o u t ( ) ;
9.4.3 Créer des Helpers
La notion de Helper (assistant en français) correspond à une manière détournée
d’enrichir une classe orientée-objet sans recourir à l’héritage Nous allons prendre
le cas d’un helper pour la vue Le point de départ est le suivant : si on veut enrichir la
vue avec des méthodes utiles pour tout le site, comme la mise en forme d’une date,
ou d’un montant monétaire, la solution naturelle est de créer une sous-classe MaVue
de Zend_View et d’y placer ces méthodes
Pour éviter cette démarche un peu lourde, le Zend Framework permet d’implanter
les méthodes ajoutées sous forme de helper dont le nom et la syntaxe particulière
mènent à les traiter comme des méthodes de la Zend_View Voici un exemple simple
On veut pouvoir disposer, dans chaque vue, de l’URL de base du site Cette URL
est vide si le site est directement dans la racine htdocs du site web, sinon elle doit contenir le chemin d’accès entre htdocs et la racine du site.
Pour constituer correctement les URL placées dans une vue, il faut les préfixer par l’URL de base Il serait dangereux de la placer « en dur » dans les vues, sous peine d’avoir à changer beaucoup de choses si l’organisation du serveur évolue On doit donc disposer de cette URL de base dans les scripts de vue
Pour cela, on place dans le répertoire views/helpers le code suivant :
Exemple 9.7 zscope/application/views/helpers/BaseURL.php : la méthode ajoutée à la vue pour obtenir l’URL de base du site.
<? php
/ ∗ ∗
∗
∗ Exemple d ’ un ’ h e l p e r ’ p o u r l a vue , d o n n a n t l a
∗ b a s e de l ’ a p p l i c a t i o n
∗
∗ /
c l a s s Z e n d _ V i e w _ H e l p e r _ B a s e U r l
{
/ ∗ ∗
∗ On p r e n d s i m p l e m e n t l ’URL de b a s e d a n s l a c o n f i g u r a t i o n
∗
∗ /
Trang 2f u n c t i o n b a s e U r l ( )
{
$ r e g i s t r y = Z e n d _ R e g i s t r y : : g e t I n s t a n c e ( ) ;
$ c o n f i g = $ r e g i s t r y−>g e t ( ’ c o n f i g ’ ) ; ;
r e t u r n $ c o n f i g−>app−>b a s e _ u r l ;
}
}
Il s’agit s’une classe dont le nom est préfixé par Zend_View_Helper La partie variable du nom de la classe indique le nom de la méthode étendant la Zend_View, soit, ici, baseUrl()
On peut utiliser cette méthode comme si elle appartenait à la vue Voici par
exemple comment on insère dans le layout le logo du site en préfixant par l’URL de base le chemin d’accès au répertoire images :
<img s r c = " <? php echo $ t h i s−>BaseUrl ( ) ; ? > / images / l o g o png "
b o r d e r = " 0 " a l t = " Webscope " t i t l e = " A c c u e i l "
/ >
La vue Zend est déjà pré-équipée avec de nombreux helpers servant, par exemple,
à faciliter la production de formulaires Je vous renvoie à la documentation pour plus
de détails à ce sujet
9.5 LE COMPOSANT MODÈLE DU ZEND FRAMEWORK
La technique dite Object-Relational Mapping (ORM) associe une couche
orientée-objet à une base relationnelle sous-jacente Elle est très importante pour réaliser le Modèle d’une application, puisque la plupart des objets du modèles sont persistants
et doivent être sauvegardés dans la base de données
9.5.1 L’ORM du Zend Framework
Zend propose un ORM pour établir la correspondance entre la base et le code PHP Cet ORM est moins puissant (du moins à l’heure ó ces lignes sont écrites) que
d’autres comme Ruby On Rails ou Hibernate, mais il gagne en simplicité et
peut-être en performances Cela constitue une manière élégante de cacher la structure
relationnelle et de s’épargner dans de nombreux cas (mais pas tous) l’expression de
requêtes SQL répétitives
L’ORM du ZF ne s’appuie pas sur de longs documents de configuration XML Il se contente de réclamer quelques définitions légères dans des classes dédiées, et fournit ensuite des mécanismes sympathiques de parcours dans la base de données en suivant les liens définis par les clés primaires et étrangères Toutes les classes ORM d’une application doivent hériter de l’une des trois classes abstraites suivantes
1 Zmax_Db_Table_Abstract assure la correspondance avec les tables de la base ;
Trang 32 Zmax_Db_Rowset_Abstract eassure la correspondance avec les ensembles
de lignes (autrement dit, les résultats de requêtes) ;
3 Zmax_Db_Row_Abstract assure la correspondance avec les lignes d’une table
ou d’un résultat de requête
Comme leur nom l’indique, ces classes sont abstraites ; on ne peut donc pas
les instancier directement Il faut fournir une classe concrète, héritant de Zmax_Db_Table_Abstract, pour chaque table intervenant dans le modèle ORM
de l’application
9.5.2 Le modèle ORM de l’application
Le premier exemple est la classe Artiste, assez simple à définir puisqu’elle n’a pas de clé étrangère la liant à une autre table dans notre modèle de données La correspondance est définie dans un fichierArtiste.php situé dans application/models.
Exemple 9.8 zscope/application/models/Artiste.php : Le modèle de la table Artiste
<? php
c l a s s A r t i s t e e x t e n d s Z e n d _ D b _ T a b l e _ A b s t r a c t
{
p r o t e c t e d $_name = ’ A r t i s t e ’ ;
p r o t e c t e d $ _ p r i m a r y = ’ i d ’ ;
/ / P a s d ’ a u t o−i n c r é m e n t a t i o n
p r o t e c t e d $ _ s e q u e n c e = f a l s e ;
}
Cet exemple représente la correspondance minimale d’une classe sous-typant Zmax_Db_Table_Abstract Les propriétés suivantes doivent être définies :
1 $_name est le nom de la table ;
2 $_primary est le nom de la clé primaire (un tableau s’il y a plusieurs attri-buts) ;
3 $_sequence est à true (par défaut) si la clé est auto-incrémentée ; rappelons que pour des raisons de portabilité aucune de nos clés n’est auto-incrémentée, mais vous pouvez omettre cette propriété et lui laisser sa valeur par défaut si vous choisissez l’auto-incrémentation
La clé primaire peut être obtenue directement de la base si elle n’est pas précisée (comme nous l’avons fait dans la classe TableBD implantant le modèle de notre
MVC light) La faire figurer explicitement facilite la compréhension de la classe
ORM
Voyons maintenant un exemple pour la table Film, dans laquelle figurent deux clés étrangères, l’une vers la table Artiste (le metteur en scène) et l’autre pour le pays.
Pour simplifier, nous ne donnons la correspondance ORM que pour la première
Trang 4Exemple 9.9 zscope/application/models/Film.php : le modèle de la table Film
<? php
c l a s s F i l m e x t e n d s Z e n d _ D b _ T a b l e _ A b s t r a c t
{
p r o t e c t e d $_name = ’ F i l m ’ ;
p r o t e c t e d $ _ p r i m a r y = ’ i d ’ ;
/ / P a s d ’ a u t o −i n c r é m e n t a t i o n de l a c l é
p r o t e c t e d $ _ s e q u e n c e = f a l s e ;
/ / R é f é r e n c e à l a t a b l e A r t i s t e
p r o t e c t e d $ _ r e f e r e n c e M a p = a r r a y (
" R e a l i s a t e u r " => a r r a y ( / / Le " r ô l e " d e l ’ a s s o c i a t i o n
" c o l u m n s " => ’ i d _ r e a l i s a t e u r ’ , / / La c l é é t r a n g è r e
" r e f T a b l e C l a s s " => " A r t i s t e " , / / La c l a s s e ORM d e l a
t a b l e r é f é r e n c é e
" r e f C o l u m n s " => " i d " , / / La c l é é t r a n g è r e r é f é r e n c é e
)
) ;
}
Le tableau $_referenceMap contient un élément pour chaque table référencée
par une clé étrangère Au niveau de l’ORM, on ne donne pas la référence à des tables,
mais aux classes ORM qui les encapsulent Ici, on fait référence à la classe Film définie précédemment Le but est bien d’avoir un modèle d’objets se référençant les uns les autres, en dissimulant les accès à la base de données
Chaque élément de $_referenceMap est lui-même un tableau donnant l’infor-mation définissant le lien entre les deux tables sous-jacentes Elle doit permettre la reconstitution de la jointure pour calculer le lien entre les lignes des deux tables On retrouve e toutes les informations de la clause FOREIGN KEY en SQL
Comme $_referenceMap est un tableau associatif, on donne un nom à l’as-sociation qui n’est pas nécessairement le nom de la table référencée, mais désigne plutôt le rôle de cette dernière dans l’association Ici, l’entité référencée dans la table
Artiste est le réalisateur du film, et ce rôle apparaît explicitement comme nom de
l’association On peut trouver plusieurs clés étrangères vers la même table, qu’il faut distinguer par un nom spécifique
Le dernier exemple que nous donnerons montre la correspondance pour une
association plusieurs à plusieurs C’est la table Role qui établit cette association entre
les films et leurs acteurs dans la base de données Au niveau des classes ORM, nous avons besoin d’une classe Role définie comme suit :
Exemple 9.10 zscope/application/models/Role.php : le modèle de la table Role
<? php
c l a s s R o l e e x t e n d s Z e n d _ D b _ T a b l e _ A b s t r a c t
Trang 5p r o t e c t e d $_name = ’ R o l e ’ ;
p r o t e c t e d $ _ p r i m a r y = a r r a y ( ’ i d _ f i l m ’ , ’ i d _ a c t e u r ’ ) ;
/ / P a s d ’ a u t o−i n c r é m e n t a t i o n
p r o t e c t e d $ _ s e q u e n c e = f a l s e ;
/ / R é f é r e n c e au f i l m e t à l ’ a r t i s t e
p r o t e c t e d $ _ r e f e r e n c e M a p = a r r a y (
" F i l m " => a r r a y (
" c o l u m n s " => ’ i d _ f i l m ’ , / / Nom d e l a c l é é t r a n g è r e
" r e f T a b l e C l a s s " => " F i l m " , / / C l a s s e d e l a t a b l e
r é f é r e n c é e
" r e f C o l u m n s " => " i d " / / C l é p r i m a i r e r é f é r e n c é e
) ,
" A r t i s t e " => a r r a y (
" c o l u m n s " => ’ i d _ a c t e u r ’ , / / Nom d e l a c l é é t r a n g è r e
" r e f T a b l e C l a s s " => " A r t i s t e " , / / C l a s s e d e l a t a b l e
r é f é r e n c é e
" r e f C o l u m n s " => " i d " / / C l é p r i m a i r e r é f é r e n c é e
) ,
) ;
}
On met en œuvre les mêmes principes que précédemment avec le tableau
$_referenceMap, qui contient cette fois deux entrées
Une nouvelle application doit non seulement définir le schéma relationnel avec SQL, mais également le modèle des classes ORM Il ne semble pas exister à l’heure actuelle d’outil pour engendrer automatiquement les classes à partir des tables, mais cela viendra sûrement Soulignons que les classes ORM héritent d’un ensemble de fonctionnalités pour gérer les échanges avec la base de données, mais qu’elles consti-tuent aussi une place de choix pour implanter la « logique métier » de l’application Dans notre cas cette logique est limitée car notre application est essentiellement orientée vers l’exploitation d’une base de données, sans traitement complexe En général, le modèle comprend des méthodes déterminant le comportement fonction-nel, « métier », des objets, en plus de leur caractère persistant
Dernière remarque avant de passer à l’exploitation des fonctionnalités de persis-tance : ces classes sont des classes concrètes qui peuvent être instanciées en objets qui communiquent avec les tables de la base Elles ont donc besoin d’une connexion Celle-ci n’apparaît pas ici, car elle est définie une fois pour toutes par l’appel à setDefaultAdapter() dans le fichierindex.php