zend framework php 01 2011

47
5/2009

Upload: boufedec59

Post on 27-Jun-2015

536 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Zend Framework PHP 01 2011

5/2009�

Page 2: Zend Framework PHP 01 2011

� �/�0��

Page 3: Zend Framework PHP 01 2011

www.phpsolmag.org �

Table des matières

Page 4: Zend Framework PHP 01 2011

Table des maTières

1/2011

Le périodique phpsolutions est publié parSoftware Press Sp. z o.o. SK

Bokserska 1, 02-682 Varsovie, PologneTél. 0975180358, Fax. +48 22 244 24 59

www.phpsolmag.org

Président de Software Press Sp. z o.o. SK : Paweł Marciniak

Directrice de la publication : Ewa Łozowicka

Dépôt légal : à parution

ISSN : 1731-4593

Rédacteur en chef : Łukasz Bartoszewicz

Couverture : Sławomir Sobczyk

DTP : Sławomir Sobczyk [email protected]

Composition : Sławomir Sobczyk

Correction : Valérie Viel, Thierry Borel, Barbara Bourdelles

Bêta-testeurs : Brice Favre, Valérie Viel, Cyril David,

Christophe Milhau, Alain Ribault, Stéphane Guedon, Eric Boulet, Mickael Puyfages, Christian Hernoux,

Isabelle Lupi, Antoine Beluze, Timotée Neullas, Yann Faure, Adrien Mogenet, Jean-François Montgaillard,

Turmeau Nicolas, Jonathan Marois, Wilfried Ceron, Wajih Letaief, François Van de Weerdt, Eric Vincent,

Franck Michaël Assi, Francis Hulin-Hubard, Nicolas Dumas, David Michaud.

Les personnes intéressées par la coopération sont priées de nous contacter :

[email protected]

Publicité : [email protected]

Pour créer les diagrammes on a utilisé le programme

AVERTISSEMENTLes techniques présentées dans les articles

ne peuvent être utilisées qu’au sein des réseaux internes. La rédaction du magazine n’est pas

responsable de l’utilisation incorrecte des techniques présentées. L’utilisation des techniques présentées peut

provoquer la perte des données !

VARIA7 ActualitésActualités du monde du développement.Christophe Villeneuve

OUTILS8 Comment réussir son projet CRMFrédéric de ConseilsMarketing.frEn mettant en place un logiciel de CRM, vous allez faire la même chose que votre commerçant préféré, mais de manière automatisée et structurée. Pour vous accom-pagner dans cette démarche, nous allons vous présen-ter les 6 règles d’or pour réussir un projet de CRM, le planning prévisionnel pour ne négliger aucune étape clé et enfin les 17 erreurs à éviter pour que la mise en place de votre logiciel ne se transforme en cauchemar.

PROJETS16 Définition d’une base de données avec l’ORM Doctrine dans un projet SymfonyTlili BelgacemL’utilisation de la programmation Orientée Objet est une priorité pour un développeur, mais ce point n’est plus aussi exact qu’avec l’utilisation des frameworks de mapping Objet / Relationnel (ORM). Depuis la sortie de PHP5, plusieurs frameworks ont été développés, per-mettant le développement des grandes applications en respectant les normes de programmation Objet.

DOSSIER20 Acquérir de la vitesse avec Zend Framework – part IIIStéphane GuédonAprès une interruption de quelques mois, Stéphane Guédon reprend le cours des articles visant à améliorer l’usage que nous faisons des diffé-rents composants du Zend Fra-mework. Dans cet article il vous présentera les com-posants Zen_Cache ma-is aussi, plus largement, la notion de politique de cache.

�/�0��

Page 5: Zend Framework PHP 01 2011

Table des matières

9/20101

Extension ZIP pour PHP

Page 6: Zend Framework PHP 01 2011

� �/�0��

Table des matières

PRATIQUE26 Développer un centre d’appel avec Asterisk et VtigerCRM – deuxième partieRandriamifidy Bezama MarolahyDans ce second article de notre série, nous allons par-ler du VtigerCRM. En premier lieu, vTiger CRM est une application intégrée de gestion de la relation client (CRM), aisément utilisable en Intranet ou depuis Inter-net grâce à un simple navigateur. Intégralement distri-buée sous licence libre (LGPL depuis la version 5), la solution vTiger CRM est principalement destinée aux PME/PMI opérant en mode BtoB.

FICHE TECHNIQUE30 Guide de conception de formulaires en HTML avec traitement PHP, ergonomie, accessibilitéMatthieu LacroixLe formulaire est un moyen de faire interagir le visiteur sur votre site. Moteur de recherche, espace de contact ou encore forum de discussion, nombreuses sont ses applications. Vous verrez comment les concevoir et les traiter.

POUR LES DÉBUTANTS36 SQL : extraire des donnéesCilia Mauro, Magali ContensinLes bases de données sont très utilisées dans les ap-plications Web. La création, l’interrogation et la manipu-lation des données de la base sont réalisées en SQL. Dans cet article, vous apprendrez à extraire des don-nées d’une table et à les trier avec SQL.

41 SQL : les jointuresCilia Mauro, Magali ContensinDans les articles précédents vous avez appris les ba-ses du langage SQL. Vous êtes capables de réaliser des bases de données simples, d’y insérer des don-nées et de les interroger. Dans l’article précédent, vous avez vu comment extraire des données d’une table. Cet article explique comment interroger plusieurs tab-les en même temps.

Page 7: Zend Framework PHP 01 2011

Actualités

www.phpsolmag.org

Calendrier de l’avent 2010Chris Shiflett publie le calendrier de l’Avent PHP, avec des astuces d’experts PHP pour tout le monde. Chaque jour, du �er décembre jusqu’au ��, vous découvrirez une nouvelle astuce. http://phpadvent.org/2010

PHP 5.3.4La nouvelle version de PHP 5.�.� vient de sortie. Elle n’apporte pas de nouvel-les fonctions, mais seulement quelques évolutions de certaines fonctionnalités comme le choix de l’encodage pour get_html_translation_table. Bien sur, certains correctifs ont été en même temps déployés. C’est pourquoi il est important d’effectuer la migration.http://www.php.net

Xdebug ToggerxDebug Togger est une nouvelle bar-re pour le navigateur Safari. Celle-ci va vous aider à déboguer vos appli-cations PHP, comme cela existe pour les autres navigateurs. Bien entendu, vous bénéficiez des fonctionnalités Xdebug.. https://github.com/benmatselby/xde-bug-toggler

WePloyWePloy est un outil de déploiement, utilisé par la société WePlay. Celui-ci est réalisé en PHP et publié par Ra-smus Lerdorf. Cet outil peut être utilisé pour déployer n’importe quel type de projet PHP. Un communiqué est disponible pour montrer son installation et sa configu-ration. http://dev.wepay.com/blog/2010/11/30/weploy-wepays-deployment-tool/Posh 3.0La nouvelle version de Posh �.0 vient de sortir. Elle propose de nouveaux connecteurs pour vous permettre d’obtenir plus d’informations à partir de CMS (Typo �), de Forum (phpBB), mais aussi de sites actualités (Google News).En plus, d’autres points importants ont été incorporés : compatilité avec les smarphones, refonte de l’interfa-ce, apparition d’un menu intelligent, etc ...http://www.portaneo.org/portal/index.php#tab/1

Magix cjquery Magix cjquery vient de publier la no-uvelle version. Cette librairie est ma-intenant compatible avec PHP 5.�. Par ailleurs, celle-ci apporte aussi quelqu-es correctifs et une évolution de la documentation. Cette version est plus souple, plus simple et la récupération des erreurs est plus précise.http://magix-cjquery.com

Informations autour de PHP 5.2.xCe mois de décembre est un mois important pour PHP et aussi un nouveau tournant pour ce langage, c’est à dire : Le 1er point concerne la mise à disposition de la nouvelle version PHP 5.2.16 qui remplace la version 5.2.15, sortie quelques jours avant. Cette version corrige une régression dans la mise en oeuvre de la fonction open_basedir introduite avec la version précédente. Par ailleurs, un correctif im-portant pour PDO::pgsql a été ajouté.Le 2ème point concerne la fin du support de la branche PHP 5.2. Ainsi vous n’aurez plus de nouvelles versions mineures corrigeant de nouveaux bugs éventuels. Le 3ème point est par conséquent la suite logique des 2 premiers points présentés ci-dessus, et conseillés par la Team de PHP. Il s’agit de la migra-tion de PHP 5.2 vers PHP 5.3. Pour effectuer la migration vers PHP 5.3, un guide détaillé est disponible sur le site de PHP.net (http://php.net/migration53) pour vous permettre de réali-ser l’opération. Ce guide parle de nombreux sujets qui vont vous intéresser pour exploiter au mieux celle-ci, qui comprend : les nouvelles fonctionnali-tés, les nouveaux paramètres, les nouveaux filtres, les nouvelles méthodes, les expressions retirées, les nouvelles classes, etc...http://www.php.net

phpPgAdminphpPgAdmin est une ap-plication web réalisée en langage PHP destinée à faciliter la gestion du SGDB PostgreSQL.La version 5.0 vient de sortir et il s’agit d’une version majeure et com-patible pour PHP 5.0 et plus, pour PostgreSQL 7.4 minimum. Elle propose de nombreux correctifs de bugs et de nouvelles fonctionnalités, comme : • La compatibilité avec les versions de PostgreSQL 8.4 et 9.x.• Nouveau schéma de l'export.• Amélioration de l'interface.• Application graphique amélioree.• Ajout de nouveaux thèmes.• De nombreuses traductions disponibles (comme le Français).• Prise en charge multi-domaine FK.• Etc.

Par ailleurs, de nouvelles langues ont été ajoutés (Tchèque, Grec, Brésilien Portugais, Galicien)http://www.postgresql.org

Rédaction des actualités : Christophe Villeneuve

Page 8: Zend Framework PHP 01 2011

�/�0���

Outils

D’ailleurs votre boucher du coin de la rue fait tous les jours du CRM sans le savoir lorsque vous passer le voir :

• il vous reconnaît et vous appelle par votre nom,• il vous propose votre plat préféré, ses fameuses cô-

tes d'agneaux bien fines comme d’habitude,• il vous demande comment vont les enfants,• il vous rajoute quelque grammes de viande en

plus car vous êtes un bon client (avec un petit clin d'œil),

• il vous propose de goûter son pâté en croute fait maison car il est sûr qu'il va vous plaire,

• …

En mettant en place un logiciel de CRM, vous allez faire la même chose que votre commerçant préféré, mais de manière automatisée et structurée. Pour vous accompagner dans cette démarche, nous allons vous présenter les 6 règles d'or pour réussir un projet de CRM, le planning prévisionnel pour ne négliger aucune étape clé et enfin les 17 erreurs à éviter pour que la mise en place de votre logiciel ne se transforme pas en cauchemar.

Nous resterons volontairement totalement agnostique sur la solution de CRM à adapter, car la méthodologie de mise en place du logiciel de CRM restera identique

quelque soit l'éditeur de logiciel sélectionné. La mise en place d’une solution CRM est souvent initiée par une volonté d’améliorer un des éléments de la relation clients d’une entreprise :

• Assurer un meilleur suivi du travail de ses commer-ciaux.

• Simplifier les processus et traitements internes.• Faciliter le partage d'informations et la communica-

tion.• Faire de la prise de commandes directement chez

les clients.• Proposer un extranet client pour gérer les deman-

des SAV.• Mettre en place des chaînes de fidélisation sur sa

base clients.• Obtenir une meilleure gestion de son SAV.

Dès lors, naît le projet CRM.Pourtant, très vite le chef d’entreprise, le responsable

commercial, le responsable information… à l’origine du projet se rend compte que pour appliquer cette nouvel-le stratégie, il faudra repenser l’organisation actuelle et parfois, revoir profondément la façon de travailler des collaborateurs.

Or, toucher à l’organisation commerciale ou techni-que de l’entreprise, c’est toucher à un élément sensible

Comment réussir son projet CRMPour agir efficacement sur ces � facteurs il est incontournable de mettre en place une solution de CRM. Si cet acronyme anglais pour Customer Relationship Management (ou Gestion de la Relation Client) fait encore peur à de nombreuses entreprises, et pour certains reste synonyme d’usine à gaz, le principe est pourtant simple.

Cet article explique :• Cet article sur le CRM va vous donner toutes les clés pour réus-

sir la mise en place de votre solution de CRM. • Nous allons nous concentrer sur les principes fondamentaux :• Vos clients car c’est grâce à eux qui nait votre chiffre d’affaires,

le carburant qui fait tourner votre entreprise.• Vos prospects, car en période de crise plus que jamais vous ne

pouvez plus vous permettre de laisser passer une affaire.

Ce qu’il faut savoir :• Aucun prérequis.

Page 9: Zend Framework PHP 01 2011

CRM

www.phpsolmag.org �

Pourtant, ce n’est pas aussi si simple que cela en a l’air : comme nous l’avons précisé en introduction, un projet de CRM touche les processus de l’entrepri-se et modifie la manière de travailler des utilisateurs. De plus, les populations touchées sont souvent les commerciaux et le service technique qui sont, par nature, des „électrons libres” peu habitués à la rigu-eur et qui appliquent une organisation qui leur est propre.

En effet, au contraire des comptables, des person-nes de la production… il est parfois difficile d’obliger un commercial à utiliser un logiciel dont il ne voit pas immédiatement les bénéfices et l’intérêt. La gestion du changement et l’adhésion des équipes est donc le défi majeur à relever dans la mise en place d’une solution de CRM. Pour le relever avec succès, il est indispensable de suivre les 6 règles d’or décrites ci-dessous.

Intégrer le projet de CRM dans la stratégie de l’entrepriseLe CRM est l’outil qui permettra d’appliquer la stratégie de l’entreprise : il est le bras armé de la stratégie. C’est pourquoi, avant de choisir le bon outil, il faut d’abord savoir où vous voulez aller et ce que vous souhaitez faire.

Pour cela, il faut faire un diagnostic:

• Quel est mon métier ? Quels secteurs ou services je veux développer ? Où est-ce que je souhaite dé-velopper mon activité ? Comment évoluera mon secteur d’activité ? Que dois-je faire pour me diffé-rencier de mes concurrents …

• Comment vais-je réussir à atteindre ces objectifs ? Que doivent faire mes salariés pour atteindre mes objectifs ? Quels seront leurs futurs besoins ? Est-ce que je suis équipé, dans ce but, en hommes, en matériel… ?

C’est uniquement après avoir fait ce diagnostic que le projet CRM peut démarrer. En effet, mettre en place un CRM doit être le bras armé de la stratégie, et non le contraire. Le CRM n’est qu’un outil qui doit répon-dre à un besoin. C’est lors de cette étape que la di-rection validera le projet et le contenu du projet de CRM.

De plus, en ayant défini où nous voulons aller, il sera bien plus facile de définir le périmètre du CRM, ce qu’il doit faire en priorité et ce qu’il n’est pas nécessaire qu’il fasse dans un premier temps. Un document de cadrage doit absolument être rédigé. Le formalisme et l’écriture des informations sont indispensables à la réussite d’un projet de CRM car, d’une part, cela permet de valider ce qui doit être fait (évitant ainsi les malentendus) et, d’autre part, cela engage les personnes sur ce qui doit être fait.

et crucial de son activité, ce qui va plus loin que la simple mise en place d’un logiciel. La mise en place du CRM changera des habitudes qui sont parfois solidement an-crées… Nous verrons d’ailleurs dans ce dossier que la résistance au changement est l’un des défis majeurs des projets de CRM.

Pourtant, lorsqu’un projet CRM se concrétise, il se transforme souvent en un véritable outil de création de valeur ajoutée en offrant de nouveaux services aux clients, en donnant plus de productivité aux commer-ciaux, en améliorant la satisfaction clients…

Au niveau de la mise en place d’une solution de CRM, il existe deux grandes typologies de projets. Le projet de CRM Simple, qui se retrouve dans les petites struc-tures, avec peu de personnels à équiper et peu d’inte-ractions entre les différents services (ex : pourvoir une petite équipe commerciale de 2 ou 3 personnes séden-taires). Dans ce cas, le projet touche relativement peu de personnes, l’enjeu majeur sera de comprendre les besoins de cette équipe et d’y adapter l’outil tout en op-timisant leur activité.

Le projet CRM Evolué, qui se retrouve dans les plus grandes entreprises et dans le cas où la solution de CRM influe plusieurs services de l’entreprise (ex : mi-se en place d’un logiciel pour une équipe commerciale nomade et sédentaire avec liaison à l’ERP avec, en plus, l’installation d’un outil pour structurer l’activité du Service SAV). Dans ce cas, le projet de CRM sera bien plus délicat à gérer et nécessitera un suivi précis et ri-goureux. En effet, non seulement il faudra prendre en compte la dimension technique, mais en plus (et sur-tout !) il ne faudra pas négliger la dimension humaine. Cela passera, entre autres, par la prise en compte des besoins réels des opérationnels, la vérification que l’outil pourra gérer correctement ces besoins métier et le suivi de la mise en place de la nouvelle organi-sation. C’est pourquoi nous vous présenterons ici les 6 règles d’or à respecter pour réussir son projet CRM, qu’il soit simple ou évolué ainsi que les 17 erreurs à ne pas commettre, puis un planning prévisionnel avec les grandes étapes à respecter.

Au niveau opérationnel, la distinction entre un Projet Simple et Evolué se fera par une plus grande souples-se et moins de formalisme, mais il n’en demeurera pas moins indispensable de suivre toutes les 6 règles d’or car même un petit projet de CRM risque d’échouer en cas de sous-estimation du travail technique et humain à accomplir.

Les 6 règles d’or à respecter pour qu’un projet de CRM soit un succès !Pour tous ceux qui ont déjà installé un logiciel de comp-tabilité ou de gestion, ou un nouvel OS, mettre en place un logiciel de CRM semble probablement très simple : il suffit d’installer le logiciel, de former les employés, et c’est fini…

Page 10: Zend Framework PHP 01 2011

�/�0���0

Outils

Ce document de cadrage :

• Définira le périmètre de l’application : utilisation uni-quement par les commerciaux ou aussi par d’autres services (marketing, SAV, comptabilité…).

• Structurera le projet : qui, quoi, où, pourquoi, com-ment (planification, répartition claire des rôles de chacun et attribution d’un budget).

• Proposera (éventuellement) une stratégie de dé-ploiement en phases pour une conduite du chan-gement optimale (ne pas tout changer radicalement et d’un seul coup !).

• Intègrera des actions de communication fortes pour faire adopter le changement : réunions de lance-ment, mise en avant des avantages pour les sala-riés.

Important : ce document n’est pas figé dans le temps. Il est encore une fois indispensable de le faire vivre et évoluer au cours du projet et de le mettre à dispo-sition de tous les acteurs du projet à chaque nouvelle version. Le document de cadrage doit être la Bible du projet et comprendre de manière exhaustive ce qui doit être mis en place. Ce document doit être présenté au prestataire information, et il servira de base pour définir par écrit ce qui sera exactement réalisé. Ce document ne devra pas laisser de place au doute ou aux approxi-mations : il devra précisément indiquer ce que veut l’en-treprise (une fonction ne doit pas être expliquée par une simple phrase, mais avec une description détaillée et il-lustrée).

Il ne faut surtout pas oublier, dans cette réflexion, que le CRM nécessitera sans doute une évolution de l’en-treprise au niveau :

• Culturel (évolution des mentalités) : il ne s’agit plus de travailler seul dans son coin mais avec le CRM, les informations seront échangées entre collègues et services (il faut donc définir ce qui sera écrit, les „normes” d’écriture…), l’informatique sera utili-sé pour automatiser certaines tâches (il faut donc voir ce qui peut être automatisé dans les proces-sus, remettre en cause ce qui se faisait aupara-vant…).

• Organisationnel : revoir des manières de penser et de travailler parfois archaïques, remplacer les processus écrits et les validations par des traite-ments informatiques…

Lutter contre la résistance au changementC’est l’ennemi N°1 de tout projet de CRM… Trop sou-vent, l’outil de CRM est perçu comme le nouveau „jou-jou” de la direction pour contrôler l’activité des salariés ou obtenir des tableaux de bord… et non comme une aide dans l’atteinte des objectifs des autres salariés de l’entreprise.

Vous devez donc définir clairement à tous les acteurs concernés par le CRM les buts et objectifs de ce pro-jet pour éviter les incompréhensions et mettre en avant les bénéfices et les avantages apportés par cette solu-tion. La rengaine On fait comme ça depuis toujours, et ça marche…, On a toujours eu l’habitude de faire cela comme ça…, encore une usine à gaz qui va nous em-pêcher de travailler… sont les réactions typiques aux-quelles vous faites face quand vous proposez un chan-gement en entreprise.

Attendez-vous donc à devoir passer quasiment autant de temps à convaincre de l’intérêt du CRM qu’à mettre en place l’application ! Vous vous ren-drez vite compte que changer des habitudes néces-site patience et capacité à convaincre. En effet, la résistance au changement est l’écueil majeur des projets CRM : la mauvaise appréciation et la sous-estimation des changements entraînés par le logi-ciel de CRM est la première cause d’échec. Car il ne faut pas s’y tromper : un logiciel de CRM imposera une plus grande rigueur et changera la vie des utili-sateurs.

Avec le CRM, les collaborateurs devront appren-dre à privilégier l’écrit à l’oral, ce qui requerra une amélioration qualitative et quantitative de saisie des données … afin qu’en contrepartie, ces informations soient utilisables par tous les services de l’entreprise. Au niveau opérationnel, vous vous rendrez compte que les changements susceptibles de vous sembler mineurs peuvent entraîner une résistance importante au changement … Par exemple, imposer l’enregis-trement dans le logiciel de tous les appels entrants, les rendez-vous… ennuiera plus d’un commercial qui trouvera toutes les excuses du monde pour ne pas le faire !

C’est pourquoi, pour obtenir l’adoption du projet CRM, il faut toujours mettre en avant au moins un bénéfice concret pour les utilisateurs :

• pour un commercial, avoir des alertes pour relan-cer automatiquement les clients dont la décision d’achat est proche, identifier les clients inactifs de-puis X jours, personnaliser les e-mailings de l’entre-prise avec leurs coordonnées, obtenir des fiches de prospection avec des coordonnées automatique-ment pré-saisies ou pré-qualifiées grâce à un for-mulaire rempli sur internet…

• Pour le marketing, c’est pouvoir vérifier l’efficacité des actions marketing, obtenir des remontées ter-rains plus rapides et plus concrètes (obtenir des photos des produits concurrents…), communiquer plus rapidement vers les commerciaux (fiches pro-duits, publicités…).

• Pour le service technique, c’est avoir une base de connaissances utilisable en interne, mais aussi en externe (FAQ)…

Page 11: Zend Framework PHP 01 2011

CRM

www.phpsolmag.org ��

En plus des bénéfices apportés par l’outil CRM, il est souvent important d'apporter un plus aux populations qui utiliseront l’application :

• Offrir un nouvel ordinateur pour utiliser le logiciel.• Donner un nouveau Smartphone avec GPS qui per-

met en plus de consulter le CRM.• Mettre en place une prime qualitative sur la saisie

d'informations dans le CRM.

Analyser la situation actuelle et analyser son évolution avec la solution de CRMLa solution de CRM ne doit pas être considérée comme une brique de plus du système d’information, mais com-me un ciment qui relie toutes les informations conte-nues dans les différents logiciels de l’entreprise. Pour que l’intégration se passe au mieux, il faut préférer le bien au mieux : c’est-à-dire commencer en douceur en mettant en place le logiciel de CRM là où il est le plus utile (ex: pour gérer le SAV), et ensuite intégrer les autres pans de l’activité de l’entreprise, une fois que cette première intégration sera digérée et assimilée.

Il faut que le CRM donne le plus rapidement des résul-tats concrets et tangibles incitant les utilisateurs à pen-ser que cette application est bien conçue pour leur faire gagner du temps. Il y a lieu d’identifier en priorité où l’or-ganisation est perfectible et montrer que le CRM per-met d’améliorer la situation. Dans le même ordre d’idée, la tentation est de demander aux opérationnels d’entrer plus d’informations, car en théorie, tout peut être fait avec un CRM.

Or, si trop d’informations tuent l’information, trop d’in-formations tuent à coup sûr un projet CRM. Donc, lors de la phase de mise en place, il faut absolument de-mander aux opérationnels de remplir le minimum de données dans le système, et d’enrichir au fur et à me-sure les fiches afin de s’assurer que seules les informa-tions strictement nécessaires sont entrées.

Vouloir imposer un changement radical dans toute l’entreprise du jour au lendemain est le plus grand fac-teur d’échec. C’est pourquoi dans cette phase, il est im-portant d’identifier où les informations sont disponibles ou créées, pour savoir ensuite comment / où / par qui elles seront intégrées, et comment les processus peu-vent être simplifiés ou automatisés.

Suite à ce premier audit de l’organisation, il faut alors passer à l’analyse de ce qui peut être récupéré dans la solution de CRM. Par exemple, les données comptables sont dans le logiciel de gestion, les plannings peuvent être gérés dans MS Outlook, les informations techni-ques dans une base de connaissances sous MS Excel, les fiches de visites dans des fiches papier… Tout ces silos d’informations doivent être inter-connectés par le logiciel de CRM.

Ceci fait, vous devez distinguer les informations in-dispensables à l’entreprise de celles qui sont accessoi-

res. En effet, la récupération des données est rarement intégrale, et il faut savoir accepter une perte minimale d’informations (ex : pas d’historique des visites de plus de 2 ans…).

Plus vous souhaitez récupérer des informations, plus le coût sera élevé (et ce n’est pas proportionnel : les 20% restant de l’information à récupérer peuvent faire gonfler de 80% le coût de la récupération des données à cause d’une saisie semi-automatique et manuelle).

C’est pourquoi si vous possédez un logiciel de comp-ta / gestion, il ne faudra pas hésiter à contacter votre éditeur pour savoir quels sont les ponts proposés avec les logiciels de CRM du marché, ou éventuellement s’il n’en propose pas.

Rappelez-vous aussi du principe Garbage In / Gar-bage Out, c’est-à-dire que si les données à l’origine sont mauvaises, alors les données que vous obtiendrez dans le CRM seront mauvaises…

C’est pourquoi, souvent un projet de CRM passe par une phase d’analyse des données existantes, avec un choix de remettre à plat les données ou d’une reprise partielle, voire d’une re-qualification des informations pour repartir d’une base saine.

Il est important de s’assurer que le CRM utilise une base de données saine afin de ne pas remettre en question non pas l’outil, mais ce qu’il produit comme information.

Enfin, pour réduire les coûts de votre projet, choi-sissez absolument une solution qui est en standard proche de vos besoins. Évitez un maximum la person-nalisation et le développement sur mesure. C’est non seulement un coût supplémentaire, mais surtout des évolutions difficiles à prévoir dans les années suivan-tes (évolution des besoins, des systèmes…).

Donner des informations utiles aux utilisateursCela peut sembler une évidence, mais de nombreux projets CRM sont mis en place par la direction sans donner la parole aux véritables utilisateurs de la solu-tion…

Il faut donc faire une étude des besoins auprès des commerciaux, techniciens, équipes marketing… et sa-voir ce dont ils ont vraiment besoin, ce qu’il faudrait améliorer. Néanmoins, faites attention au syndrome j’aimerais bien qu’il fasse aussi… qui apporte des fonc-tions qui ne seront au final pas forcément utilisées et qui sont plus du domaine du rêve…

Un bon début est d’analyser l’utilisation du logiciel actuel et de ses limites (par une observation sur le ter-rain), et son inadéquation avec la stratégie de l’entre-prise.

Pour cela, vous devez impliquer les opérationnels dans la réflexion. Un des clés de votre succès sera d’in-clure dans le projet les employés qui sont connus et re-connus dans la structure (les anciens ou ceux qui ont

Page 12: Zend Framework PHP 01 2011

�/�0����

Outils

une très bonne connaissance des processus formels et informels de l’entreprise).

Il est essentiel de prendre le temps de la réflexion et de l’analyse des besoins. Avant de commencer à consul-ter les éditeurs de logiciels, il faut réfléchir à son projet, analyser l’existant, les améliorations à apporter. Tout le temps passé à réfléchir en amont, c’est au minimum 2 à 3 fois plus de temps économisé lors de la mise en place du projet (et donc des coûts en moins).

Pour l’analyse de la situation de l’entreprise, vous pouvez vous inspirer de la Méthode Lean initiée chez les constructeurs automobiles Japonais comme Toyo-ta (voir http://fr.wikipedia.org/wiki/Lean). Les principes fondateurs de la méthode Lean sont la recherche de la performance par l’amélioration continue, l’élimination des gaspillages et l’optimisation des processus inutiles qui alourdissent l’entreprise. Cette méthode passe par une impulsion des opérationnels, et non pas celle de la direction.

Une fois que vous savez où vous devez aller, il faut lister les nouvelles données et les nouveaux processus à mettre en place et vous assurer qu’ils seront accep-tés. En particulier, ces changements ne doivent pas en-traver et alourdir le travail de vos salariés, ou alors ap-porter un bénéfice concret qu’il faudra expliquer.

N’oubliez pas que les effets liés au logiciel de CRM n’entraîneront pas forcément des gains immédiats vi-sibles pour tout le monde… Pour éviter la désaffection et le faible taux d’adoption, il faudra communiquer, re-communiquer et encore re-re-communiquer sur l’inté-rêt du projet… et surtout, formaliser les nouveaux pro-cessus via un cahier des procédures qui deviendra la référence. Encore une fois, il faudra privilégier l’écrit à l’oral.

Formaliser le projet CRM dans l’entreprise et assurer le suiviPour qu’un projet de CRM soit un succès, il faut lui don-ner de la visibilité et ne pas en faire un projet secret ou un Serpent de Mer. Il faut communiquer en interne sur le projet de CRM afin que les utilisateurs se l’appro-prient, et sentent qu’ils sont partie prenante au projet. Pour cela, n’hésitez pas à mettre en place une réunion officielle de lancement interne, à donner des informa-tions sur l’avancement dans la newsletter interne de l’entreprise ou par un e-mail information…

Ayez toujours en tête que 50% de la réussite d’un pro-jet de CRM vient non pas de l’outil informatique utilisé mais de la mise en place du projet CRM et de la person-nalité de la personne qui est en charge du projet. Pour cela, il faut créer dès le départ un comité de pilotage CRM qui sera l’élément moteur dans la mise en place du projet de CRM :

• un chef de projet (le sponsor) : si possible, désigner un opérationnel aguerri aux habitudes de l’entrepri-

se, qui aura occupé plusieurs fonctions, qui est res-pecté… et qui est favorable au projet ! A défaut, le responsable commercial ou marketing mais évitez, dans la mesure du possible, le responsable infor-matique qui a une vue technologique et moins «be-soins utilisateurs». Le chef de projet sera le lien entre l’entreprise et le prestataire. Vous devrez lui confier un «ordre de mission» écrit avec le cadre du projet, le budget, le planning prévisionnel… le tout devant être négocié avant le début du projet.

• un groupe de réflexion : ce comité rassemble des opérationnels (pas forcément des managers, bien au contraire !) qui seront impliqués dans le projet de CRM et qui feront en sorte que le projet convienne bien à la réalité du terrain.

• un membre du comité de direction qui pourra pren-dre les décisions, faire avancer le projet en cas de blocage et montrer l’implication de la direction dans le projet (NB : le projet devra être lancé officielle-ment et annoncé comme un des objectifs prioritai-res de l’année sans que son importance puisse être remise en cause).

Tous doivent être responsables de la mise en place du projet, être clairement nommés et obtenir du temps dans leur agenda pour traiter ce projet.

Des réunions et points doivent être programmés en avance (par exemple, toutes les 2 semaines) et il fau-dra faire la chasse à l’absentéisme. Toutes les réunions auront un objectif et un ordre du jour, avec une liste des tâches à effectuer par personne et des dates limites pour accomplir le travail. Le chef de projet veillera à la bonne réalisation du travail par un point (physique, par téléphone ou par émail) sur l’avancement des tâches entre les réunions car, d’expérience, ce n’est souvent qu’à l’approche de la date limite que les collaborateurs commencent à réfléchir au travail à effectuer.

Pour assurer le succès du projet de CRM, le budget alloué et les objectifs à atteindre seront clairement dé-finis. L’équipe gardera le moral et verra sa motivation maintenue car chaque petite victoire sera fêtée (une coupe de champagne…) durant l’avancement du projet, que cela soit pour le lancement du projet, pour la réa-lisation de la première bêta… Le projet de CRM sera plus facilement adopté si un nom lui est donné.

Contrôler que la solution est adoptée et qu’el-le répond aux besoinsUne fois la solution de CRM mise en place, il est in-dispensable de valider son adéquation par rapport aux objectifs initiaux, mais également faire en sorte qu’elle réponde aux besoins des utilisateurs.

La formation initiale aux utilisateurs est essentiel-le : elle peut être effectuée par un prestataire pour les utilisateurs pilote, puis déléguée aux salariés qui ont été formés en premier, mais il est essentiel que tous

Page 13: Zend Framework PHP 01 2011

CRM

www.phpsolmag.org ��

sachent bien utiliser le produit et en voient les impli-cations.

Il faut aussi prévoir une piqûre de rappel 1 à 2 mois après la mise en place de l’application pour répondre aux nouvelles questions et attentes car, dans la plupart des cas après la mise en place du système et une uti-lisation quotidienne, de petits ajustements sont indis-pensables. Généralement, il faut prévoir 5 à 10% du montant du projet total pour ces ajustements post mise en production.

En parallèle, vous devez faire un suivi de l’atteinte des objectifs du projet. Avant la mise en place du projet, vous définissez les indicateurs clés liés au succès du logiciel de CRM : des fiches avec des adresses e-mail, un taux de NPAI plus faible, un taux diminué d’affaires perdues, une augmentation du CA de N%… Ainsi, vous savez où vous en êtes et, éventuellement, identifiez des points de blocage et améliorez la situation et, surtout, montrez les bénéfices concrets de la mise en place du CRM.

Le planning de mise en place d’un logiciel de CRMLes délais de mise en place d’une solution de CRM sont très variables d’une entreprise à l’autre.

Par exemple, une petite entreprise de 3 ou 4 person-nes mettra en place une solution de CRM Simple en environ 1 à 2 jours, mais une entreprise qui a un projet de CRM Evolué organisera un planning sur plusieurs mois.

D’une manière générale, les projets de CRM Evolués durent entre 5 mois et 1,5 an entre le début de la ré-flexion et la mise en place réelle.

Pour vous guider, voici les 17 étapes principales à prendre en compte pour la mise en place d’une solu-tion de CRM.

0 - Analyse de la situation actuelle dans l’entreprise (problématique, logiciels existants…).

1 – Définition des objectifs du projet de CRM par les responsables de l’entreprise. Définition du périmètre exact du projet, pour éviter les malentendus en cours ou en clôture de projet. Cet ordre de mission sera obliga-toirement écrit et désignera des responsables du projet. Ce document de cadrage officialise la nomination des membres du groupe de travail et du chef de projet.

2 – Étude des besoins auprès des opérationnels.3 – Analyse des logiciels disponibles du marché

et premier choix d’une courte liste de solutions (3 ou 4 au maximum).

4 – Réception des propositions suite aux demandes de devis / appels d’offres auprès des éditeurs de logi-ciels de CRM ou du prestataire informatique habituel.

5 – Re-formulation des besoins de l’entreprise pour s’assurer qu’ils correspondent effectivement aux ob-jectifs.

6 – Choix de la solution à retenir, avec définition d’un planning de mise en place par le prestataire.

7 – Test par un échantillon d’utilisateurs (les bêta tes-teurs)

8 – Information sur l’avancement du projet à la struc-ture (comité de direction et collaborateurs).

9 – Finalisation du projet par le prestataire.10 – Présentation du projet aux employés de l’entre-

prise.11 – Formation des utilisateurs.12 – Mise en place de la solution de CRM et ajuste-

ments opérationnels.13 – Bilan du projet 1 mois après.14 – Optimisation de la solution.15 – Formation de perfectionnement (1 à 2 mois après

la mise en place du projet).16 – Optimisation continue de la solution avec évolu-

tion des besoins de l’entreprise et de l’environnement économique.

Bien entendu, avant de mettre en place l’application, il faut l’avoir bien testé pour éviter les lancements en fanfare qui se transforment en Bérérézina (surtout, véri-fier que l’intégration des données se passe bien avec le système d’information de l’entreprise).

Il faut aussi bien préparer les supports de cours, les guides de procédures… pour une acceptation plus ra-pide par les utilisateurs. Penser à nommer des experts dans chaque service qui seront les interlocuteurs de ni-veau 1 sur les problèmes les plus simples (générale-ment, les membres du comité CRM).

Dans les premiers jours, il conviendra de maintenir en parallèle les 2 systèmes en permettant, si nécessai-re, une bascule entre les deux systèmes, mais il faudra passer le plus rapidement possible au nouveau sys-tème et ne surtout pas laisser perdurer une cohabita-tion.

17 erreurs qui font échouer les projets de CRM La mise en place d’une solution de CRM est souvent une première dans une entreprise et, généralement, le responsable n’a pas l’expérience dans la mise en place de ce genre d’applications. C’est pourquoi, sans une préparation sérieuse et une anticipation, le projet risque facilement de glisser dans le temps, voire être remis en question par les collaborateurs de l’entreprise. Pour éviter cela, voici une liste des erreurs à ne surtout pas commettre dans la mise en place d’un projet CRM :

0 – Négliger la résistance au changement dans l’en-treprise.

1 – Acheter une solution sans avoir au préalable ana-lysé ses besoins, l’évolution de son entreprise et sa stratégie, la récupération des données existantes…

2 – Imposer le logiciel de CRM dans son entreprise sans communication, ni concertation, ni pédagogie.

Page 14: Zend Framework PHP 01 2011

�/�0����

Outils

3 – Utiliser tout son budget pour l’achat de la solution de CRM sans penser à la récupération des données, à la personnalisation et à la formation des salariés.

4 – Ne pas nommer un responsable du projet de CRM dans l’entreprise, ou nommer une personne non influente ou qui dénigrera le projet ou une personne qui pense-ra à la technologie avant de penser aux hommes…

5 – Ne pas avoir un soutien visible et continu de la direction.

6 – Vouloir tout automatiser tout de suite, sans transi-tion ni phase progressives de mise en place… et ajou-ter en même temps des nouvelles technologies qui vont révolutionner les habitudes des utilisateurs.

7 – Ne pas établir un planning avec des responsables et ne pas vérifier que les jalons sont bien suivis.

8- Ne pas mettre en avant les bénéfices concrets et pratiques pour les utilisateurs.

9 – Voir trop grand et mettre en place un système trop complet… Il faut toujours commencer par le minimum d’informations et enrichir sur demandes lors des pha-ses de tests et d’utilisation.

10 – Ne pas prendre en compte les remontées des utilisateurs, ou ne pas expliquer pourquoi il n’est pas possible de le faire pour l’instant.

11 – Laisser les anciens outils aux utilisateurs, ce qui freinera l’adoption du nouveau logiciel.

12 – Ne pas lier le CRM avec les autres logiciels de l’entreprise, ce qui laisse encore des doubles saisies et des informations partielles.

13 – Ne compter que sur soi-même pour personnali-ser le logiciel et assurer la formation des utilisateurs.

14 – Faire appel à un prestataire qui ne connaît pas les applications de CRM.

15 – Ne pas réaliser avec son prestataire un docu-ment de cadrage définissant avec précision les élé-ments à réaliser.

16 – Rester flou dans ses demandes à son prestatai-re, en espérant qu’il comprendra le but recherché.

17 – Traiter son prestataire comme un exécutant, et non pas comme un partenaire.

L’étude menée par Sage en 2005 révèle que les pre-mières difficultés des projets CRM sont la récupération des données et la résistance au changement.

Dans un projet de CRM, il est essentiel de travailler avec son prestataire informatique en partenariat et en toute transparence. En effet, contrairement au logiciel de Comptabilité où les tâches sont normées et les pro-cessus clairement standardisés, avec une application de CRM, c’est la manière dont l’entreprise fonctionne qui est touchée.

En effet, ici, il n’y a pas de norme à suivre, c’est l’appli-cation qui doit s’adapter au mieux à l’entreprise et non l’inverse.

C’est pourquoi, pour travailler efficacement avec son revendeur, il ne faudra pas lui demander 3 ou 4 fonc-

tions par e-mail ou avec un cahier des charges d’une page, mais le rencontrer et définir ensemble un cahier des charges le plus complet possible.

Parfois, l’échec d’un projet CRM vient aussi des uti-lisateurs eux-même… Un exemple typique est celui du jeune commercial qui arrive dans l’entreprise et qui, à force de persuasion, finit par convaincre son patron d’acheter «la solution miracle CRM» qu’il a utilisée à l’école… En effet, notre jeune cadre dynamique utili-sera d’abord le logiciel dans son coin, puis le diffusera à ses collègues sans avoir un plan d’ensemble, sans prendre en compte la globalité de l’organisation de l’en-treprise (ou en voulant tout révolutionner) ni l’intégration au système d’information de l’entreprise ou les relations inter-service (éviter les doubles saisies, permettre un partage des données...), ce qui conduira à un rejet en bloc de la solution de CRM.

Pour conclureLa mise en place d’une solution de CRM dans une en-treprise est indispensable dans notre environnement économique incertain, mais auparavant il faut mener un travail de réflexion important.

En effet, au contraire d’une solution de bureautique, d’un logiciel de comptabilité… qui sont finalement très normés et standardisés, le CRM lui ne s’installe pas sans une analyse et de la communication avec toutes les personnes impliquées.

Son impact sur la manière de travailler des collabo-rateurs, sur les processus internes et l’image de l’en-treprise est telle qu’il est indispensable de cadrer son projet et de réfléchir à la globalité, mais également aux détails.

Les deux éléments majeurs à surveiller pour réussir son projet CRM sont :

Le cadrage initial du projet, qu’il faudra faire évoluer au fur et à mesure de l’avancement. Ce document sera obligatoirement formalisé et validé.

L’adoption par les utilisateurs, par une analyse concrè-te des besoins, mais aussi par une communication en interne pour convaincre du bien-fondé de la mise en place de l’outil.

En conclusion, il faut retenir que la mise en place d’une solution de CRM est finalement un projet à la fois technique et humain qu’il faut mener à bien en tenant compte des spécificités de l’organisation de l’entrepri-se. Et comme chaque entreprise est différente, à cha-que fois il faut s’adapter à ses particularités via la mé-thodologie que vous venons de vous présenter.

FRéDéRIC De COnseILsMARkeTIng.FRConseilsMarketing.fr est un des premiers sites sur le Marketing en France, il donne toutes les semaines des conseils concrets et pra-tiques pour trouver des prospects, fidéliser ses clients et gagner du temps.

Page 15: Zend Framework PHP 01 2011

CRM

www.phpsolmag.org �5

5/201050

Pour les débutants

49

Club .PRO

Pour plus de renseignement : [email protected] Rejoignez le Club .PRO

Ston eld InworldSton eld Inworld propose aux entreprises des solutions globale d’intègration d’Internet et des Univers Virtuels dans leur stratégie de développement. Au-delà de ses services, la société consacre 30% de ses ressources à des travaux de R&D sur le e-Commerce et le e-Learning dans les Mondes Virtuels.

COGNIX SystemsConseil, conception et développement d’applications évoluées pour les systèmes d’informations Internet/intranet/extranet. Alliant les compétences d’une SSII et d’une Web Agency, Cognix Systems conçoit des applicatifs et portails web à l’ergonomie travaillée et des sites Internet à forte valeur ajoutée.http://www.cognix-systems.com

Intelligence PowerConseil, Expertises, Formations et Projets E-business centrés au tour du cśur de métier : la Business Intelligence. Intelligence Power vous propose des solutions innovantes pour aligner la technologie sur la stratégie de votre entreprise.http://www.intelligencepower.com

Web AllianceVous souhaitez être en première page des moteurs de recherche ? Rejoignez-nous, 100% des clients Web Alliance sont en 1ère page de Google. Web Alliance, société de conseil spécialisée dans le référencement internet, vous propose son expertise (référencement, liens sponsorisés, web-marketing).www.web-alliance.fr

Anaska FormationAnaska est le spécialiste des formations sur les technologies OpenSource. En partenariat avec MySQL AB, Mandriva, Zend et d'autres acteurs de la communauté, Anaska vous propose un catalogue de plus de 50 formations dédiés aux technologies du Libre.http://www.anaska.com

WEB82Création et hébergements de sites web pour particuliers, associations, entreprises, e-commerce. Développement entierement aux normes W3C (www.w3.org) de sites web de qualité, au graphisme soigné et employant les dernieres technologies du web (PHP5, MySQL5, Ajax, XHTML, CSS2).http://www.web82.net

Core-TechsExpert des solutions de gestion et de communication d’entreprise en Open Source, Core-Techs conçoit, integre, déploie et maintient des systemes de Gestion de Contenu Web, de Gestion Documentaire, de Gestion de la Relation Client (CRM), d’ecommerce et de travail ollaboratif.http://www.core-techs.fr

POP FACTORYPoP Factory,SSII spécialisée Web. Développement de solutions applicatives spéci ques ; offre de solutions packagées : catalogue numérique, e-commerce, livre/magazine numérique, envoi SMS. Nous accompagnons nos clients tout au long de leur projet : audit, conseil, développement, suivi et gestion.http://www.popfactory.com / [email protected]

Blue Note SystemsSpécialistes en CRM Open Source, nous proposons une offre complète de prestations sur la solution SugarCRM. Notre valeur ajoutée réside dans une expertise réactive et une expérience des problématiques de la GRC. Nous vous aidons à tirer le meilleur parti de votre solution CRM.http://www.bluenote-systems.com

5/201050

Pour les débutants

49

Club .PRO

Pour plus de renseignement : [email protected] Rejoignez le Club .PRO

Ston eld InworldSton eld Inworld propose aux entreprises des solutions globale d’intègration d’Internet et des Univers Virtuels dans leur stratégie de développement. Au-delà de ses services, la société consacre 30% de ses ressources à des travaux de R&D sur le e-Commerce et le e-Learning dans les Mondes Virtuels.

COGNIX SystemsConseil, conception et développement d’applications évoluées pour les systèmes d’informations Internet/intranet/extranet. Alliant les compétences d’une SSII et d’une Web Agency, Cognix Systems conçoit des applicatifs et portails web à l’ergonomie travaillée et des sites Internet à forte valeur ajoutée.http://www.cognix-systems.com

Intelligence PowerConseil, Expertises, Formations et Projets E-business centrés au tour du cśur de métier : la Business Intelligence. Intelligence Power vous propose des solutions innovantes pour aligner la technologie sur la stratégie de votre entreprise.http://www.intelligencepower.com

Web AllianceVous souhaitez être en première page des moteurs de recherche ? Rejoignez-nous, 100% des clients Web Alliance sont en 1ère page de Google. Web Alliance, société de conseil spécialisée dans le référencement internet, vous propose son expertise (référencement, liens sponsorisés, web-marketing).www.web-alliance.fr

Anaska FormationAnaska est le spécialiste des formations sur les technologies OpenSource. En partenariat avec MySQL AB, Mandriva, Zend et d'autres acteurs de la communauté, Anaska vous propose un catalogue de plus de 50 formations dédiés aux technologies du Libre.http://www.anaska.com

WEB82Création et hébergements de sites web pour particuliers, associations, entreprises, e-commerce. Développement entierement aux normes W3C (www.w3.org) de sites web de qualité, au graphisme soigné et employant les dernieres technologies du web (PHP5, MySQL5, Ajax, XHTML, CSS2).http://www.web82.net

Core-TechsExpert des solutions de gestion et de communication d’entreprise en Open Source, Core-Techs conçoit, integre, déploie et maintient des systemes de Gestion de Contenu Web, de Gestion Documentaire, de Gestion de la Relation Client (CRM), d’ecommerce et de travail ollaboratif.http://www.core-techs.fr

POP FACTORYPoP Factory,SSII spécialisée Web. Développement de solutions applicatives spéci ques ; offre de solutions packagées : catalogue numérique, e-commerce, livre/magazine numérique, envoi SMS. Nous accompagnons nos clients tout au long de leur projet : audit, conseil, développement, suivi et gestion.http://www.popfactory.com / [email protected]

Blue Note SystemsSpécialistes en CRM Open Source, nous proposons une offre complète de prestations sur la solution SugarCRM. Notre valeur ajoutée réside dans une expertise réactive et une expérience des problématiques de la GRC. Nous vous aidons à tirer le meilleur parti de votre solution CRM.http://www.bluenote-systems.com

Page 16: Zend Framework PHP 01 2011

�/�0����

Projets

L ’utilisation de la programmation Orientée Objet est une priorité pour un développeur, mais ce point n’est plus exact à 100% qu’avec l’utilisation des fra-

meworks de mapping Objet / Relationnel (ORM). Depuis la sortie de PHP5, plusieurs frameworks ont été dévelop-pés, permettant le développement des grandes applica-tions en respectant les normes de programmation Objet.

Toutefois, il y a nombres de frameworks de map-ping Objet / Relationnel (ORM) visant à ce que l’utilisa-teur puisse manipuler ses tables de données comme si c’étaient des objets.

Doctrine est l’un des ORM les plus connus qui exi-stent actuellement. Il est utilisé dans des frameworks très connus (Symfony, Zend Framework), et est aussi simple à prendre en main que puissant. Doctrine est basé sur le noyau du framework Hibernate (java). Nous allons voir ensemble l’utilisation de cet ORM dans un projet PHP développé sous le framework Symfony.

symfonySymfony est un framework PHP, développé par Sensio labs en octobre 2005 en PHP5 (version 5.2.4).

Au départ de chaque projet Symfony, vous devriez préparer votre base de données : une étape de spéci-fication des besoins et de la conception de la base de données du projet est nécessaire.

Après la validation du schéma conceptuel, on passe à la création de la base réelle avec le langage relation-nel SQL.

Symfony propose une couche de mapping objet-relationnel (ORM) et une couche d’abstraction de données, depuis la version 1.2, les développeurs de Sensio ont choisi Doctrine comme étant l’ORM par défaut et ainsi remplacer l’ancien Propel.

L’utilisation de la ligne de commande de Symfony permet la génération des classes modèles, classes for-mulaires et classes filtres ainsi la génération du code SQL de la base de données. Alors comment Doctrine comprend-il notre schéma conceptuel ? Comment con-nait-il les tables et les contraintes d’intégrité ?

Dans un projet symfonyPour décrire le schéma de notre base de données dans un projet Symfony on doit utiliser un fichier de configu-ration spécifique, c’est le fichier schema.yml situé dans NomProjet\config\doctrine\. La plupart des fichiers de configuration de symfony sont au format YAML. Selon le site officiel, YAML est un standard de sérialisation de données compréhensibles par un humain, quel que soit le langage de programmation.

YAML est un langage simple qui décrit les données. Comme PHP, il a une syntaxe pour les types simples comme les chaînes, les booléens, les décimaux ou les entiers.

Il y a une chose importante dont vous devez vous so-uvenir lorsque vous utilisez l’indentation dans un fichier YAML : une indentation doit être faite avec un ou plu-sieurs espaces, mais jamais avec les tabulations.

Définition d’une base de données avec l’ORM Doctrine dans un projet symfonyLa plupart des services informatiques d’aujourd’hui sont devenus des applications web. Ces applications sont caractérisées par un degré de complexité très élevé, en effet, le travail du développeur est devenu plus complexe, étant donné l’évolution des langages de développement, des bases de données et des différentes plateformes de développement.

Cet article explique :• Définition d’une base de données sous l’ORM Doctrine. • Relations un à plusieurs.• Relations plusieurs à plusieurs.• Bonnes pratiques.• Commandes Symfony Doctrine.

Ce qu’il faut savoir :• Le lecteur devra connaître les principes de programmation

orientée objet en PHP5, néanmoins des notions concernant le framework Symfony et l’orm Doctrine.

Page 17: Zend Framework PHP 01 2011

symfony et Doctrine

www.phpsolmag.org ��

Vous pouvez inclure des mappings dans des séries si vous le souhaitez ou vous pouvez inclure des séries dans des mappings comme ceci :

Voici le schéma sur lequel nous allons travailler dans cet article :schema.yml

C’est un schéma conceptuel simplifié pour une agen-ce de location de voitures où on a deux tables Voiture et Utilisateur et où on veut enregistrer les opérations de location de chaque voiture.

Détaillons la structure YAML de la Classe (table aussi) VoitureEn premier lieu on doit spécifier le nom de la Classe (qui sera aussi le nom de la table).

Ensuite, en commence à décrire la liste des colon-nes de la table (qui seront les attributs de la classe modèle qui va être générée avec Doctrine), pour cela le mot clé columns doit être utilisé.

Puis, pour chaque colonne on doit spécifier une li-ste des options qui ressemblent à l la description des champs dans SQL.

On doit spécifier pour chaque champ le type de don-nées tel que : string, boolean, integer, date, datetime...

On ajoute la taille du champ puis on spécifie d'autres propriétés optionnelles comme notnull, default, primary, autoincrement …

Relations un à plusieursLa spécification des cardinalités lors de l’étape de con-ception a fixé le type des relations entre les tables ; en fait, dans ce premier exemple on a une relation de type un à plusieurs, donc une voiture peut être louée par un et un seul utilisateur et ce dernier peut louer plusieurs voitures à la fois. Donc on doit ajouter id_utilisateur comme clé étrangère dans la table Voiture puis on doit créer la relation entre les deux entités comme suit :

La description des relations est la partie le plus im-portante dans l’élaboration du schéma YAML, car ils se-ront utilisés après, dans les classes modèles et formu-laires pour récupérer un Objet ou une liste des objets B à partir d’un Objet A.

Comme pour les colonnes, une relation doit avoir un nom, pour cela deux cas possibles :

• Choisir le même nom, celle de la deuxième table qui participe dans la relation.

• Choisir un nom significatif (tel est notre cas), ma-is on doit obligatoirement ajouter la propriété class parmi la liste des propriétés qu’on doit définir pour la relation (dans le premier cas cette propriété n’est plus obligatoire car Doctrine comprend qu’il doit avo-ir une autre table avec le même nom de la relation).

Après la génération de la classe associée, on aura là deux nouvelles méthodes, dites magiques (getter et setter):1. getLocataire() : retourne l’utilisateur qui a loué la

voiture actuelle. Exemple : B = new Voiture () ; B. getLocataire () ; // retourne l’utilisa-

teur qui a loué B.2. setLocataire(Objet de type Utilisateur) :

pour louer la voiture actuelle à un utilisateur passé en paramètres.

Exemple : A = new Utilisateur () ; B. setLocataire(A) ; // location de la vo-

iture B par l’utilisateur A

[local : id_utilisateur] : sert à fixer la colonne de la table Voiture (où on a déclaré la relation), utili-sé pour établir la liaison avec la table Utilisateur (la clé étrangère).

Chapitre 1: Introduction TypesChapitre 2’: Introduction Helpers I18n Javascript

Voiture: columns: id_voiture : { type : integer , notnull : true , primary : true } marque: { type : string(30) , notnull : truen } puissance : { type : integer , notnull : true } etat : { type : boolean , notnull : true }Utilisateur : columns: id_utilisateur: { type : integer , notnull : true , primary : true } nom: { type : string(20) , notnull : true } prenom : { type : string(20) , notnull : true }

Voiture: columns: id_voiture : { type : integer , notnull : true , primary : true } marque: { type : string(30) , notnull : truen } puissance : { type : integer , notnull : true } etat : { type : boolean , notnull : true } id_utilisateur { type : integer , notnull : true } relations: Locataire: { class: Utilisateur, local : id_utilisateur , foreign : id_utilisateur , foreignAlias : Voitures }Utilisateur : columns: id_utilisateur: { type : integer , notnull : true , primary : true } nom: { type : string(20) , notnull : true } prenom : { type : string(20) , notnull : true }

relations: Locataire: {class: Utilisateur, local : id_utilisateur , foreign : id_utilisateur }

Page 18: Zend Framework PHP 01 2011

�/�0����

Projets

Dans ce cas, la définition de la relation est un peu spéci-fique : on doit spécifier les deux tables et ainsi l’associa-tion qui va les relier..

• On a la même chose pour le nom des relations (Lo-cataires) ainsi que pour [foreignAlias : Voitures].

Pour des raisons sémantiques il est préférable de mettre les noms au pluriel, puisque on travaille plu-sieurs à plusieurs.

• [ refClass : Location] : c’est là où se situe la différence entre les types de relations, ici on doit spécifier le nom de l’association entre les deux enti-tés.

Ainsi vous avez une idée plus ou moins complète de la définition de votre schéma YAML. Une fois terminé, vous pouvez générer les classes modèles et les clas-ses formulaires où vous pouvez constater que, dans le cas d’une relation un à plusieurs Doctrine présente le champ id_utilisateur par une liste de choix simple (un seul choix) ; par contre dans le cas de relations plu-sieurs à plusieurs vous aurez dans les deux formula-ires une liste de choix multiple des objets.

Bonne pratiqueDoctrine propose pas mal de best practice pour simpli-fier le schéma de la base de données et pour rendre plusieurs taches automatiques :

1. La clé primaire : doctrine peut s’occuper de ce champ. Si vous n’avez pas spécifié la propriété [primary :true] à l’une des colonnes, Doctrine ajoute une colonne et lui donne le nom id, son ty-pe sera integer et en autoincrement. Cela pour sim-plifier notre schéma. Ensuite, si vous utilisez le champ de la clé primaire dans une relation vous po-uvez utiliser le nom id bien sûr.

Dans le cas où vous utilisez Oracle comme SGBD, lors de la génération de la base réelle Doctrine va créer une séquence pour le champ id.

2. L’enregistrement de la date d’ajout et de modifi-cation des données d’une table est parfois ob-ligatoire ; tel est le cas d’une table d’inscription à titre d’exemple, on veut connaître la date d’in-scription et la date de modification d’inscription. Doctrine offre la possibilité de gérer ces informa-tions et leurs mises à jour automatique sans inte-rvention du développeur (dans la partie Métier) ; pour cela on doit ajouter la ligne suivante au début de chaque table où l’on veut avoir ces in-formations.

[foreign : id_utilisateur] c’est le champ qui fait référence à la clé étrangère dans la table Utilisa-teur.[foreignAlias : Voitures] : c’est une propriété très importante ; comme on a fixé le nom de la relation (Locataire) dans la table Voiture on doit aussi donner le nom de la même relation mais cette fois dans la ta-ble Utilisateur. Au lieu de redéfinir la totalité de la rela-tion dans la table Utilisateur on utilise foreignAlias pour donner seulement le nom de la relation et Doctrine joue son rôle.

La classe Utilisateur générée avec Doctrine va contenir deux fonctions comme pour la classe Voiture, mais le type de retour est un peu différent puisque c’est une relation un à plusieurs.

1. getVoitures() : retourne la liste des voitures (Do-ctrine Collections) louées par l’utilisateur actuel.

2. setVoitures (Doctrine Collections of Voiture) : po-ur affecter une collection de voitures à un Utilisa-teur.

Autres options :

• Dans le cas actuel Doctrine comprend bien que c’est une relation un à plusieurs mais on peut spéci-fier les options type (one ou many) ou foreigntype (le type de relation coté entité).

Relations plusieurs à plusieursCe type de relation nécessite une association entre les deux tables, puisqu’un utilisateur peut louer plusieurs voitures et une voiture peut être louée par plusieurs uti-lisateurs, donc notre schéma sera comme suit :

Une troisième table (appelée aussi association), est ajoutée pour gérer la relation plusieurs à plusieurs.

Voiture: columns: id_voiture : { type : integer , notnull : true , primary : true } marque: { type : string(30) , notnull : truen } puissance : { type : integer , notnull : true } etat : { type : boolean , notnull : true } relations: Locataires: { class: Utilisateur, local : id_voiture , foreign : id_utilisateur , foreignAlias : Voitures , refClass: Location }Utilisateur : columns: id_utilisateur: { type : integer , notnull : true , primary : true } nom: { type : string(20) , notnull : true } prenom : { type : string(20) , notnull : true }Location: columns: id_voiture: { type : integer , notnull : true , primary : true } id_utilisateur : { type : integer , notnull : true , primary : true }

relations: Locataires: { class: Utilisateur, local : id_voiture , foreign : id_utilisateur , foreignAlias : Voitures , refClass: Location }

Page 19: Zend Framework PHP 01 2011

www.phpsolmag.org ��

Prenons l’exemple de la table Voiture :

• [actAs: { Timestampable: ~ } ] : au même niveau que columns, cette propriété permet à Doctrine d’ajouter deux champs nommés respec-tivement created_at et updated_at à notre table Vo-iture et sa classe associée. Lors de l’ajout d’une vo-iture à la base de données le champ created_at prendra la valeur de la date système, et dans le cas d’une modification d’une voiture qui existe déjà, Do-ctrine, met à jour seulement le champ updated_at.

Commandes symfony DoctrineVoici une liste des commandes Symfony (version 1.4) utilisées lors de générations du code :

• [symfony doctrine:build-model] : génération des classes modèles seulement.

• [symfony doctrine:build-forms] : génération des classes formulaires seulement.

• [symfony doctrine:build-filters] : génération des classes filtres seulement.

• [symfony doctrine:build-sql] : génération du code SQL de la base de données.

• [symfony doctrine:build-db] : création de la base de données à partir des classes modèles exi-stants.

• [symfony doctrine:build --all --no-confirmation] : permet d’exécuter toutes les com-mandes précédentes à la fois et sans demande de confirmation car Doctrine va écraser la base et en créer une nouvelle.

• [symfony doctrine:build-schema] : génération du schéma YAML à partir d’une base de données déjà existante, mais cette fois on aura des relations avec des noms non significatifs, c’est pour cela que l’utilisation de cette commande n’est pas recom-mandée.

Voiture: actAs: { Timestampable: ~ } columns: marque: { type : string(30) , notnull : truen } puissance : { type : integer , notnull : true } etat : { type : boolean , notnull : true }

BeLgACeM TLILIBelgacem TLILI, Ingénieur analyste développeur PHP5/Symfony chez Owliance Tunisie, je me suis spécialisé dans le développement web depuis 4 ans.

Page 20: Zend Framework PHP 01 2011

�/�0���0

Dossier

Avant de rentrer dans le vif du sujet et voir com-ment utiliser les différents éléments du, ou de-vrais-je dire, des différents éléments qui com-

posent le système de cache proposé par le Zend Framework, j'aimerais faire un petit détour par les prin-cipes et techniques sous-jacents aux systèmes de ca-che.

A la différence de nombreux autres Framework, ce-lui de Zend ouvre grand la boite de Pandore du cache et offre une palette extrêmement vaste de possibilités. Ceci étant à la fois un avantage et une source de pro-blème. Mais c'est toute l'histoire de ce framework ! Offrir pléthore de possibilités nécessite une bonne prépara-tion et une bonne analyse en amont du développement. J'espère que cet article vous apportera les outils et ficel-les nécessaires à un bon usage des objets de cache de Zend_Framework. Voyons déjà ce qu'est le cache.

Le cache c'est quoi ?C'est beaucoup de chose différentes mais d'une ma-nière générale le principe est toujours le même : mettre des données dans un élément de stockage rapide pour pouvoir les récupérer rapidement. Plus rapidement que par la méthode classique. Il y a de la mémoire cache dans tous les ordinateurs pour stocker des données temporaires. Et oui les données que l'on met dans un cache ont une durée de vie elle ne sont pas éternelles.

Dans le monde du web, le moyen normal est basé sur des requêtes http qui transitent sur un réseau pour demander à un serveur d'application de réaliser des tâ-

ches à partir de données conservées en base de don-nées. Des systèmes de cache voudront conserver en mémoire les résultats de requête http, les résultat de calcul réalisé par le serveur ou les résultat sde requête en base. Et ce, pour éviter d'avoir à les recalculer à cha-que fois.

Voici une description rapide, Au delà de la définition de la politique de cache, je vais entrer dans le détail des différents outils dont nous disposons.

La politique de cacheA quoi sert une politique de cache ? Son objectif ma-jeur est de définir quels seront les éléments qui néces-siteront du cache et comment nous le réaliserons. Jus-que là, cela semble simple. J'ai déjà entendu maintes fois des développeurs me dire : le cache, oh moi, je développe sans, et j'en mets ensuite là ou cela coince ! Non, mille fois non ! C'est une très mauvaise pratique et ce, même si la souplesse du système de cache de zend le permet ! En effet, cela peut avoir de lourdes conséquences sur les structures du contrôleur ou des templates et impliquer un refactoring important. Mieux vaut, en fonction de son architecture d'hébergement, de ses usages, du contenu du site, choisir ses techno-logies de stockage en cache, les éléments à y stocker et les durée de conservation. Le codage en sera plus efficace.

Quels sont les différents type de cache dont nous disposons ? Il y a quatre grandes famille de cache à mon sens :

Acquérir de la vitesse avec Zend Framework – part IIIAprès une longue interruption, je reprends le cours des articles visant à améliorer l'usage que nous faisons des différents composants du Zend Framework. Dans cet article je souhaite vous présenter les composants Zend_Cache mais aussi, plus largement, la notion de politique de cache.

Cet article explique :• Ce qu'est une politique de cache et comment la définir.• Comment l'implémenter en utilisant le Zend Framework.

Ce qu'il faut savoir :• Rien à part connaître PHP.

Page 21: Zend Framework PHP 01 2011

Zend Framework

www.phpsolmag.org ��

à recalculer tout ou partie d'une vue ou d'une action. En bref diminuer la charge CPU de votre serveur.

• Les caches métier/modèle : ces caches qui agis-sent aussi au niveau de votre applicatif, permet-tent de stocker des données brutes issues d'une base ou travaillées par des classes métier et donc d'éviter de recalculer les éléments permettant de construire des vues. Là encore l'objectif est de di-minuer la charge de vos serveurs d'application et de base de données.

Seules les deux dernières familles sont traitées par le système de cache Zend_cache.

• Le cache du navigateur : celui de votre navigateur web va stocker des images, des fichiers javaScript ou CSS, voire même des pages entières ! Tout ce-la se gère avec des balises Méta dans le header et évite de faire des requêtes sur le réseau.

• Le cache réseau : je range dans ce terme (qui n'est pas très orthodoxe je vous l'accorde) l'ensemble des systèmes de cache que l'on va trouver entre le navi-gateur et notre serveur d'application : se sont des serveurs mandataires ou des cache proxy comme Squid ou Varnish.

• Les caches de vues : qui agissent au niveau de vo-tre applicatif et dont l'objectif est de ne pas avoir

Figure 1. Le focntionnement du cache Browser

Figure 2. Le cache réseau

Page 22: Zend Framework PHP 01 2011

�/�0����

Dossier

Partant de là, quelles sont les questions à se po-ser ? Elles sont différentes selon les couches de cache concernées. Je vous propose de voir rapidement les deux premières et, par l'étude des deux secondes de voir comment Zend_cache pourra nous aider.

Le cache du navigateurAttention ce cache est un petit filou ! Les navigateurs sont bien fait et pour nous éviter de longs moments d'attente, ils gèrent un cache local dont l'objectif est de limiter au maximum les données échangées avec les serveurs Web. La Figure 1 montre un appel http vers un fichier index.php. Cette appel va retourner une page HTML. Si cette page n'est pas clairement définie com-me à ne pas cacher via le meta Cache-Control du hea-der, lors des prochains appels, le navigateur ne fera que vérifier si cette page n'a pas expirée et la réaffiche-ra sans la moindre requête. Il en est de même pour les éléments qui la constitue comme les fichiers javascript, CSS ou les images. C'est très pratique mais si notre fi-chier javascript est généré dynamiquement sans chan-ger son nom, il ne sera pas rechargé par le navigateur et les données seront périmées.

Pour mettre dans le Header d'une page ces informa-tions, il existe plusieurs solutions. Pour moi la plus sim-ple, c'est, dans le layout, d'ajouter la balise <META HTTP-EQUIV=»CACHE-CONTROL» CONTENT=»NO-CACHE»>. Ainsi tous les templates basés sur ce layout seront en no-cache. Ensuite plus finement au sein du controleur le framework Zend propose une fonction de l'objet ré-ponse $this->getResponse->setHeader('Cache-Control','no-cache', true). Mais cela me pose un problème dans le sens ou cela casse le MVC (Modèle Vue Contrôleur – sujet déjà abordé dans de précédent numéro de PHP Solution) puisque dans le Contrôleur (plus exactement l'action) on définit un paramètre de la vue !

Les caches réseauxSous cette appellation, je range donc tous les systèmes de cache placés entre le client et notre serveur Web. Comme montré dans la Figure 2 Les plus connus étant Squid et Varnish mais il y en a certainement d'autres.

Un serveur Squid ou Varnish est un serveur manda-taire (proxy) capable d'utiliser les protocoles FTP, HTTP et HTTPS. Il est utilisé pour filtrer des URL et comme

Listing 1. Exemples de Zend_Frontend_Cache_Core

<?php // nous avons déjà instancier l'objet cache avec le frontend Core dans $cache

$id = 'myBigLoop'; // id de cache de « ce que l'on veut cacher »

if (!($data = $cache->load($id))) { // si cache absent $data =''; for ($i=0;$i < 10000; $i++) { $dat = $data.$i; } $cache->save($data); }?>

Listing 2. Extrait de la classe Zend_Cache_Core du package Zend_Cache.

…../** * Last used cache id * * @var string $ _ lastId */ private $ _ lastId = null;….. /** * Test if a cache is available for the given id and (if yes) return it (false else) * * @param string $id Cache id * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested * @param boolean $doNotUnserialize Do not serialize (even if automatic _ serialization is true) => for internal use * @return mixed|false Cached datas */ public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false) { if (!$this-> _ options['caching']) { return false; } $id = $this-> _ id($id); // cache id may need prefix $this-> _ lastId = $id;

….....

/** * Save some data in a cache * * @param mixed $data Data to put in cache (can be another type than string if automatic _serialization is on) * @param string $id Cache id (if not set, the last cache id will be used) * @param array $tags Cache tags * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime) * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends * @throws Zend _ Cache _ Exception * @return boolean True if no problem */ public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8) { if (!$this-> _ options['caching']) { return true; } if ($id === null) { $id = $this-> _ lastId; } else { $id = $this-> _ id($id); } …...

Bonne pratique n°1 : systématiquement mettre les pa-ges html dynamiques (donc générées par votre framework) en no-cache dans le header de votre layout par exemple (Cache-Control:no-cache) et mettre des dates d'expiration sur les fichiers javascript à l'aide du Meta : Expires. Pour les fichiers javascript dynamiques, le mieux, est de les appeler avec une query string dans leur URL, comme par exemple <script src='/scripts/monBeau.js?Id=2'/>.

Page 23: Zend Framework PHP 01 2011

Zend Framework

www.phpsolmag.org ��

cache. Son rôle est de cacher des éléments statiques. Pour cela, il enregistre les URL les plus utilisées pour les mettre en cache. Oui mais voilà et si on veut pas ! La page est forcément dynamique ! Alors il ne faut pas lui permettre de mettre en cache certains type d'url ou d'extension. C'est de la conf du proxy.

Le choix entre ces deux serveurs relève plus de vo-tre hébergeur alors je ne l'aborderai pas. Vous trouve-rez sur le net des comparatifs très instructifs avec un avantage pour Varnish.

Retenez que ce type de serveur peut mettre en ca-che des fichiers javascript ou CSS minifiés, des images, en bref des contenus statiques offrants ainsi des répon-ses plus rapides aux navigateurs de vos clients.

Les Caches applicatifsLes frontendsOn va enfin parler du framework Zend. Je range dans ce chapitre les deux familles de caches applicatifs ci-tées dans l'introduction. Je fais ce choix car la structure de la librairie Zend_cache mélange les deux. D'autres frameworks (Symfony ou Cake PHP) ont une approche découpée en vues et données. La librairie Zend est, quant à elle, décomposée en frontend et backend (dé-cidément ces termes sont mis à toutes les sauces) qui permettent de configurer les deux éléments nécessai-res à la Zend_cache_factory qui aura la tâche de fabri-quer l'objet cache Zend.

C'est un peu embrouillé ? C'est effectivement pas très simple comme approche, mais avec un peu d'ex-plication les choses vont se clarifier. La partie frontend, permet de définir quel type de contenu vous voulez mettre en cache. Requête, résultat de fonction, objet, composants de vue, page ou éléments statiques (celui là c'est un sacré morceau que l'on déléguera surement à un cache proxy). La partie backend permettant de dé-finir comment vous allez (physiquement) réaliser le ca-che, file system, base de données, ram, disques.

Il ne vous restera qu'à passer les configuration de votre frontend et de votre backend à une fabrique pour créer un objet cache que vous pourrez utiliser dans votre code … C'est simple non ! Pardon, certains se demandent ce qu'est une fabrique. C'est un Design Pattern, motif de conception en français. C'est un en-semble de classes et de méthodes prédéfinies qui per-mettent d'instancier des objets complexes. C'est un constructeur intelligent. On l'utilise quand on sait que nous aurons des objets à consruire tou en partageant des définitions. L'exemple le plus fréquent est celui d'un jeu ou on construit des unités (genre Civilisation ou Age of Empire). On a le choix d'appeler les constructeurs de chaques unités (ce qui implique de coder des défi-nitions de classe, les relations entre chaque objet les utilisant, etc … à chaque nouvelle unité) ou d'avoir une fabrique qui se chargera à partir d'un patron de fabri-quer des unités.

Voyons maintenant comment bien utiliser les fron-tends de cache, pour cela, il faut se poser quelques questions pour chacun des éléments de notre page. Selon leurs réponses, les méthodes à mettre en œuvre sont différentes.

La méthode à appliquer est simple : prendre chaque page de votre site les unes après les autres et se poser les questions suivantes en en respectant l'ordre :

1. Est-il possible de cacher la page entière ? Si la ré-ponse est oui (c'est en général assez rare et réservé à vo-tre page d'accueil associée à la racine de votre site) alors le frontend Zend_Cache_Frontend_Page vous permettra de mettre en cache une page entière. Personnellement, je le trouve très complexe à utiliser car il faut (d'après la doc) désactiver le buffeur de sortie utilisé par le Dispat-cher ($front->setParam('disableoutputBuffering', true). Je ne l'utilise pas (ou plus exactement je ne l'ai pas utilisé) lui préférant Zend_Cache_frontend_output. qui fait quasi-ment la même chose en plaçant entre une balise start() et une balise end() le code que vous voulez mettre en ca-che. Avec Zend_Cache_Frontend_Page une seule bali-se start() est nécessaire. Mais cela implique de pouvoir appliquer une gestion différente à la page d'accueil par rapport aux suivantes or ,jusqu'à maintenant, mon layout sert aussi bien à cette page qu'aux suivantes !

2. Je ne peux pas mettre en cache toute la page mais est-ce que certains éléments peuvent l'être ? Je pense à un menu, un header, un footer, … en bref des parties de la page qui sont soi statiques soit faiblements dynamiques. Pour ce genre de problème, vous l'aurez compris, Zend_Cache_frontend_output est la solution. Attention ce frontend est l'exemple type de la fonction php qui résout tous les problèmes et rend le code tota-lement incompréhensible. Il ne doit pas vous affranchir d'un découpage de votre page en utilisant les compo-sants de vue que je vous ai présentés lors du précédem-ment article.

3. Ma page ressemble à un gruyère avec des élé-ments en cache et d'autres non ! Allons plus loin car

Listing 3. Exemples de Zend_Cache::factory

<?php …$frontendOptions = array ( 'lifetime' => '7200' // durée de conservation en cache en s 'automatic _ serialisation' => true);

$backendOptions = array ( //repertoire où stocker les fichiers de cache-CONTROL 'cahce _ dir' => './tmp/');

//créer un objet Zend _ Cache _ Core$cache = Zend _ Cache::factory( 'Core', 'File', $frontendOptions, $backendOptions);?>

Page 24: Zend Framework PHP 01 2011

�/�0����

Dossier

tout élément (ou presque ; mais ceux-ci doivent rester des exceptions) peut être mis en cache même quel-ques secondes. Si la vue ne peut être mise en cache peut être que des éléments métier ou model le peu-vent ? C'est à dire des objets, des résultats de fonction ou des résultats de requêtes. Là encore Le framework nous propose respectivement les frontends Zend_Ca-che_Frontend_class, Zend_Cache_Frontend_function et Zend_Cache_Frontend_core. La question qui se pose, en générale, avec ces caches est : quelle durée dois-je utiliser ? Il est très difficile (voire impossible) de la définir sans perdre en cohérence ou en réactivité. Il faut donc préférer des durées infinies et utiliser un sys-tème de clé (d'Id) qui se modifiera à chaque modifica-tion des sources de données. En utilisant par exemple un timestamp associé à la date des dernières mises à jour dans la clé qui identifiera notre enregistrement précisément.

4. Ce n'est pas un élément de page mais un fi-chier généré comme un pdf que je souhaite mettre en cache ? Là c'est Zend_Cache_Frontend_Capture qui fera votre affaire.

5. Ce n'est rien de tout cela ? Un fichier de confi-guration peut être ? Vous créer un objet Zend_Config à partir d'un fichier xml alors Zend_Cache_Frontend_File vous permettra de l'enregistrer et de pouvoir le réu-tiliser sans avoir à le régénérer. Pourquoi s'appelle-t-il File et pourquoi ne pas utiliser Zend_Cache_Frontend_Class ? Tout simplement parce que cette classe va lier l'enregistrement au fichier source et donc invalider le cache si ce fichier est modifié. Pratique non !

J'en vois déjà quelques uns se plaindre et dire : il est où le code ! Et bien en voici un tout petit peu. Je ne vais pas parcourir tous les objets car la documentation Zend me semble très précise sauf sur un point. La définition de l'ID quand on enregistre une donnée. Prenons le Listing 1 issu de la documentation ZEND. Ce listing décrit la méthode la plus simple pour gérer un enregistrement, en cache, d'une données calculées. La première fois que je l'ai lu je me suis demandé mais comment l'Id 'myBigLoop' est-il affecté à l'enregistrement ! D'après vous ? … et bien regardons le Listing 2 qui est un extrait de la classe Zend_Cache_Core qui sert de socle com-mun à toutes les classes de cache frontend. Alors vous avez compris ? Et oui le $cache->load($id) à stocker dans la variable privé $lastId 'myBigLoop' et sans Id précisé dans la fonction $cache->save() c'est celui-ci qui est utilisé. Impossible (ou presque) de le deviner sans regarder la classe. Et bien à mon avis cette prati-que est très mauvaise et je vous invite à systématique-ment remettre l'Id lors de l'appel à la fonction save() afin que votre code soit facilement lisible sans recher-cher 10, 20, 100 lignes plus avant le dernier Id utilisé !

Par cette petite étude du code, vous aurez compris que l'Id est important mais il y a un autre élément im-

portant c'est la durée de vie de votre enregistrement. Lifetime en anglais. Celui-ci est défini en option lors de la création de votre objet de cache mais peut être fixé spécifiquement à chaque objet.

Ma pratique sur ce sujet … Je l'initialise à 0 ( ce qui correspond à une durée de cache infinie) et soit j'uti-lise des Id calculés avec un timestamp (laissant le bac-kend faire lui même le nettoyage mais attention tous ne le font pas automatiquement) soit alors je spécifie une durée lors de l'appel de la fonction d'enregistre-ment save().

Je disais donc l'Id est important et pour son unicité. Elle est indispensable et un Id du genre 'myBigLoop' a toute les chances de ne pas l'être.

Ma méthode ? Je construis des Id basés sur le sché-ma suivant :

2 initiales pour l'application + le nom du contrôleur + le nom de l'action + le nom du composant de vue + un chiffress'il y a plusieurs enregistrements dans le même composant + un timestamp correspondant à la donnée de dernière mise à jour si cela est ap-plicable sinon rien. Ce qui peut donner BC/Game-Board/index/1 par exemple. Après, libre à vous de trouver une autre règle dès l'instant que l'unicité est assurée.

Pour en finir avec le code la classe Zend_Cache_Core offre les méthodes suivantes :

• un constructeur qui sera utilisé par la fabrique du cache,

• une fonction setConfig() qui permet de configurer le frontend de cache (juste au cas où vous auriez besoin de changer la conf définie dans la fabrique) cela utilise un objet Zend_Config que nous avons vu dans les articles précédents,

• setBackend() toujours au cas ou vous voudriez changer le backend à la volée …

• getBackend () le nom de la fonction parle de lui même,

• setOption () pour changer une option de la config,

• getOption () sans commentaires,• load () que nous avons déjà vu et qui permet de

charger un élément placé en cache via son Id,• test() qui ne fait que vérifier si l'enregistrement as-

socié à un Id existe,• save() que nous avons déjà vu et qui enregistre un

document,• remove() qui permet de retirer un enregistrement

du cache,• clean() qui permet de nettoyer le cache soit en

fonction d'un tag, d'un timestamp (enlève ce qui est plus vieux) ou tout ! Attention c'est la valeur par dé-faut !

Page 25: Zend Framework PHP 01 2011

Zend Framework

www.phpsolmag.org �5

• Un certain nombre de fonctions liées à la gestion des tags (promis on en reparle après) : getIdsNotMat-chingTags, getIdsMatchingAnyTags, getTags.

• Vous avez besoin de récupérer les Id alors getIds est fait pour vous.

Cette classe est surchargée pour tout les types de frontend spécifiques présentés ci avant et qui offrent au moins ces interfaces plus quelques fonctions dé-diées.

La FactoryJ'ai déjà abordé ce sujet et je pense que vous l'aurez compris, on n'instancie pas directement les objets de cache mais on utilise une factory. Le Listing 3 donne un extrait de la doc Zend pour illustrer l'usage de cette factory. C'est très simple, on définit des options pour le frontend et le backend et on les passe à l'objet static Zend_Cache::factory.

Le frontend Core je vous en ai déjà parlé mais qu'est-ce que ce backend File … voyons cela en détail.

Les backendsVoyons maintenant la notion de backend. Comme je vous l'ai dit précédemment elle correspond aux moyens physiques de réaliser la mise en cache, l'enregistre-ment. Comment choisir ? Voici quelques points :

1. Votre application tourne sur une Zend plateforme alors je pense (mais je n'ai jamais testé désolé) que le backend Zend_Cache_Backend_ZendPlatform qui a l'avantage de pouvoir gérer des tags est fait pour vous. Mais c'est quoi, un tag ? Si vous avez bien lu l'ex-trait de la classe du Listing 2, il est possible de spécifier un tag lors de l'enregistrement. Ce tag permet alors de gérer de l'invalidation ou plus exactement le nettoyage de vos enregistrements en se basant sur un tag donné. Cette fonctionnalité n'est pas disponible avec tous les backends.

2. Votre application est sur un serveur mutualisé avec de l'espace disque et sans que vous ayez la main sur l'architecture alors vous voudrez sans doute enre-gistrer le cache en système de fichier, Pour cela deux backends sont disponibles Zend_Cache_Backend_File et Zend_Cache_Backend_Sqlite. Le seul inconvénient est que ce type de cache n'est pas très rapide et que donc il ne faudra pas faire trop d'enregistrement (un peu plus avec Sqlite) sinon la fourniture de l'enregistrement deviendra aussi longue que le calcul et vous n'aurez fait que déplacer le problème.

3. Vous maîtrisez votre architecture ou vous avez un serveur avec beaucoup de RAM alors vous pouvez uti-liser des caches plus rapides qui stockent en RAM. Le Framework Zend en gère 3 : APC, Memcached et Xca-che. Premier point : aucun d'entre eux ne gère les tags. Second point il peut devenir riche (au prix de la RAM)

de stocker des données en RAM. Enfin seul memca-ched permet de partager des données entre plusieurs frontaux.

4. Vous vous dites qu'un savant mélange de ces deux solutions vous permettrait d'avoir des données mouvantes en cache rapide et d'autres plus stables en cache disque. Et bien Zend a penser à vous avec Zend_Cache_Backend_TwoLevels qui en fonction de la priorité (si si c'est aussi un des paramètre de la fonc-tion save() du Listing 2) affectée à l'enregistrement et de la place libre en cache rapide distribuera entre les deux backends votre enregistrement. Memcached per-met de faire ses opérations aussi par sa propre confi-guration.

Voilà, nous avons fait un voyage dans le monde du ca-che Zend ! J'espère que cette carte routière vous facili-tera l'accès à ces éléments.

ConclusionNous venons de voir comment étudier sa politique de cache et comment l'implémenter du coté applicatif avec le Zend Framework.

Je souhaite attirer votre attention sur le fait que la grande ouverture, le nombre important de classes dis-ponibles peuvent rendre la relecture du code difficile et donc, centraliser sa gestion de cache me semble une bonne pratique qui rend le code plus lisible.

sTéPHAne guéDOnL’auteur travaille au sein de Bestofmedia Group qui est l’un des trois plus grands groupes média internet high-tech au monde, et plus lar-gement au sein de sociétés de développement d’applications infor-matiques et ce depuis une vingtaine d’années. Tour à tour responsa-ble de développement, consultant pour une grande société de servi-ces d’un groupe international et responsable de la Direction Techni-que Nationale PHP je me suis passionné pour le framework Zend et souhaite partager mes découvertes.

Page 26: Zend Framework PHP 01 2011

�/�0����

Pratique

Dans ce second article de notre série, nous allons parler du VtigerCRM. En premier lieu, vTiger CRM est une application intégrée de gestion de

la relation client (CRM), aisément utilisable en Intranet

ou depuis Internet grâce à un simple navigateur. Inté-gralement distribuée sous licence libre (LGPL depuis la version 5), la solution vTiger CRM est principalement destinée aux PME/PMI opérant en mode BtoB, même

Développer un centre d’appel avec Asterisk et vtigerCRMAsterisk est un PBX (Private Branch eXchange ou autocommutateur telephonique Privé) open source destiné auxentreprises et vtigerCRM est l’un des meilleurs CRM (Customer Relationship Management ou Gestion de rélation client), en OpenSource. Ils sont utilisés par des nombreux projets Open Source pour les centres d’appel comme ELASTIX.

Cet article explique :• Le fonctionnement du système de téléphonie Asterisk. • Le fonctionnement du CRM vtigerCRM.• Comment installer et configurer Asterisk.• Comment créer un dialplan Asterisk. • Comment interfacer Asterisk avec le langage PHP.

Ce qu’il faut savoir :• Vous devez connaître les bases du langage PHP, l'extension so-

cket de PHP, l'extension CURL de PHP, du bash, des notions sur les protocoles SIP, UDP, TCP et les entrées sorties standard de LINUX.

Figure 1. Page d’installation de vitgerCRM

Page 27: Zend Framework PHP 01 2011

Asterisk et vtigerCRM

www.phpsolmag.org ��

si elle satisfait également les besoins des organisations non-commerciales et des associations ainsi que des départements ou filiales de grandes entreprises.

Au cours de cettarticle, nous verrons :

• quel sont les modules principaux de VtigerCRM, • comment installer VtigerCRM,• comment configurer VtigerCRM pour interagir avec

Asterisk.

Le CRM a pour but de créer et entretenir une relation mutuellement bénéfique entre une entreprise et ses clients. Dans ce mode de relations commerciales, l’en-treprise s’attache à la fidélité du client en lui offrant une qualité de service qu’il ne trouverait pas ailleurs. L’image souvent employée pour illustrer ce concept est celle de la relation entre un petit commerçant et ses clients. La fidélité de ces derniers est récompensée car le commerçant connaît leurs attentes et est capa-ble d’y répondre et de les anticiper. Le CRM recouvre une partie des concepts plus anciens de SFA pour Sa-les Force Automation (automatisation de la force de vente).

Le SFA (Automatisation des Forces de Vente) est la Gestion des prospects, comptes clients, contact et affaire. Il peut importer des données depuis une source externe comme un telechargement Web, un forum, une conféren-ce ou directement d’un email. Il peut exporter des données vers un tableur que Microsoft® Excel®, OpenOffice® Calc et d’autres logiciels pour analyser le suivi des ventes et/ou

Listing 1. Décompression et copie des fichiers vers la racine d’apache

cd /home/tar -xvzf vtigercrm.5.2.1.tar.gzcp -Rvf vtigercrm /var/www

Listing 2. Installation des dépendance

apt-get install php5-imapapt-get install php5-gdapt-get install unzipapt-get install php5-mysql

Listing 3. Modification de php.ini

max _ execution _ time = 600output _ buffering = Onpost _ max _ size = 18Mupload _ max _ filesize = 10Mallow _ call _ time _ pass _ reference = On

Listing 4. Création de fichier de vtigercrm

cd /var/www/vtigercrmchmod 777 config.inc.phpchmod 777 tabdata.phpchmod 777 install.phpchmod 777 parent _ tabdata.phpchmod 777 -Rf cache/chmod 777 -Rf storage/chmod 777 -Rf install/chmod 777 -Rf user _ privilieges/chmod 777 -Rf Smarty/cache/ chmod 777 -Rf Smarty/templates _ c/chmod 777 -Rf modules/Emails/templates/chmod 777 -Rf modules/chmod 777 -Rf cron/modules/chmod 777 -Rf test/vtlib/chmod 777 -Rf backup/chmod 777 -Rf Smarty/templates/modules/chmod 777 -Rf test/wordtemplatedownload/chmod 777 -Rf test/chmod 777 -Rf logs

Figure 2. Page d’accueil de vitgerCRM

Page 28: Zend Framework PHP 01 2011

�/�0����

Pratique

Le SAV (Service d’Assistance Utilisateur) est le rou-tage des réquetes clients. C’est à dire qu’il gère la ges-tion des tickets d’incident,la notification du statut du tic-ket au client, l’historique complet d’un ticket, la base de

identifier rapidement les éventuelles surcharges. Il permet un partage d’informations liées aux clients entre collabo-rateurs. Il est aussi possible de joindre des documents aux fiches clients.

Figure 3. Page d’accueil de vitgerCRM

Figure 4. Page de configuration d’asterisk

Page 29: Zend Framework PHP 01 2011

Asterisk et vtigerCRM

www.phpsolmag.org ��

connaissance, et Foires Aux Questions, l’intégration d’un portail de service d’aide au client et Analyse statis-tique des tickets d’incident pour une meilleure gestion des services d’assistance.

La Gestion des stocks contrôle la cycle de vie des produits, la differenciation des tarifications produits en fonction des segments de marché, la liste des produits sélectionnés par vos vendeurs et le cycle de gestion des ventes avec traitement intégré des devis, des com-mandes, et des facturations.

L’integration des emails et l’affectation des emails entrants aux contact, la gestion des listes d’envoi (mailing-lists) et l’envoi d’emailings au format HTML ou en masse à vos contact et à ‘autres utilisateurs.

Les rapports et tableaux de bord sont l entièrement personnalisables dans tous les modules, analyses du cycle de vente par stade (sales tunnel), analyses de ventes mensuelles, analyses par prescripteur, ta-bleaux de bord par stade de vente et par opportunité d’affaire.

La gestion de sécurité est la gestion des profils uti-lisateurs et droits d’accès, création des rôles d’equipe selon votre organisation interne, gestion de l’accès aux modules selon les rôles, journal d’accès de chaque uti-lisateur.

La personnalisation du Produit est la possibilité d’ajout de champs personnalisés dans tous les modules (texte, nombres, devises, listes de sélection et autres en fonction des besoins de gestion), la personnalisa-tion des onglets selon vos besoins en utilisant la fonc-tion glisser/déposer afin de masquer les modules qui ne sont pas directement liés à vos processus de vente et la personnalisation de l’interface utilisateur.

Le plugin-in vTiger pour Outlook® est la synchro-nisation des emails entre Microsoft Outlook et vTiger CRM, la synchronisation des contacts entre Microsoft Outlook et vTiger CRM et la synchronisation des tâ-ches et évènements entre Microsoft Outlook et vTiger CRM.Le plug-in vTiger pour Office® et la création de modèles de publipostage directement depuis Micro-soft Word à partir de la base de données client de vTiger CRM, Création à la demande vos documents de publipostage vers vos prescripteurs, vos rendez-vous et vos clients et vos contacts à partir de vTiger CRM.

Avec l’extension vTiger pour Thunderbird, on peut ajouter vos emails entrants de votre messagerie Mozilla Thunderbird vers vTiger CRM, Importer vos contacts de vTiger CRM vers Mozilla Thunderbird et Exporter vos adresses clients de Mozilla Thunderbird vers vTiger-CRM.

Pour installer vTigerCRM, allez dans le site de www.vtigercrm.com ou dans www.sourceforge.net pour té-lécharger la derniere version du code source de vTi-gerCRM et décompressez le dans votre racine web du serveur.

Avant de faire l’installation à partir du web, il faut d’abord installer les dépendances. Ensuite modifier le fichier php.ini dans /etc/php5/apache2/php.ini. Après on va créer les fichiers de configuration du vtigercrm.

Passons maitenant à l’installation via web. L’instal-lation web de vtigerCRM est très intuitive, il faut juste suivre les indications dans l’interface. Après avoir fter-miné l’installation, on accède à la page d’accueil de vtigerCRM.

Après avoir entré le login et le mot de passe. On entre dans l’interface principale de vtigerCRM. Nous al-lons faire un tour dans la configuration pour activer l’in-teraction par défaut avec asterisk pour le click to dial.

Nous allons completer l’adresse IP du serveur Aste-risk par 127.0.0.1 s’ils sont dans la même machine, le port d’asterisk par 5038, le login Asterisk par le nom de la section d’asterisk et le mot de passe dans manager.conf d’asterisk. Dans le prochaine tutoriel, nous allons développer un module de vtiger pour la remontée de fi-che client lors d’un appel entrant par le biais de vtlib.

Dans le prochain tutoriel nous allons créer un nou-veau module de vtiger-CRM et le faire interagir avec Asterisk. Nous verrons ensuite comment le faire intera-gir via le webmanager d’asterisk en utilisant l’extension CURL de PHP.

Figure 5. Page de configuration d’asterisk

RAnDRIAMIFIDY BeZAMA MAROLAHYL’auteur travaille en tant que consultant ntic (Nouvelles Techno-logies de l’Information et de la Communication) au sein de Team-Well Système un SSII spécialisé dans le développement web et appli-cations sur la ToIP (Téléphonie over Internet Protocol). Il réalise plu-sieurs applications web et applications internet riches. Passionné de nouvelles technologies, il cherche toujours à améliorer ses com-pétences en tant que développeur et administrateur système.Pour le contacter veuillez envoyer un mail à [email protected].

Page 30: Zend Framework PHP 01 2011

�/�0���0

Fiche technique

Un formulaire se traite en deux parties sur un site Web : une partie affichage écrite en lan-gage HTML qui invite l’utilisateur à interagir

avec le site, et toutes ses données sont ensuite en-voyées à un programme PHP sur le serveur qui va effectuer le traitement du formulaire. Ce principe est régi par l’architecture client/serveur d’Apache, où le serveur envoie les données et le client (représenté par la machine de l’utilisateur final), en bout de chaî-ne, qui les reçoit.

Construction du formulaire : première étapePour construire un formulaire en HTML, nous allons ré-fléchir à sa conception. La première étape est de re-grouper les données de même nature. Il est plus logi-que de demander nom, prénom, code postal, ville que nom, couleur des cheveux, choix de voiture, code pos-tal, film préféré, ville.

Une fois cette première étape faite, il faut ordonnan-cer la saisie des données. Saisir le code postal avant le nom, si la ville est en fin de formulaire, peut paraître illogique.

Enfin, une fois que ces deux points sont traités, pen-ser à diviser – si applicable – le formulaire en sections, très utile dans le cas d’un sondage par exemple, pour présenter une suite de X pages plutôt qu’une page uni-que de mille lignes.

Tour d’horizon des principales balises HTML utiliséesDans sa norme, l’HTML propose un vaste choix de ba-lises pour construire un formulaire. En utilisant à bon escient ces balises, il est possible de rendre ergono-mique le formulaire, c’est-à-dire plus intuitif à la mani-pulation.

Le formulaire s’ouvre par une balise <form> et se ferme par une balise </form>. Ces balises en contiennent d’autres, divisées en plusieurs catégo-ries :

• Les balises de division représentées par les jeux de champs (fieldset).

• Les balises de saisie, représentées par les zones de texte (textarea, input).

• Les balises de choix (menus déroulants, cases, ra-dios).

• Les balises d’action, représentées par les boutons (valider, …).

Bien entendu, chaque balise peut avoir quelques spéci-ficités, nous y reviendrons après.

Balises d’ouvertureIl s’agit des balises <form> et </form>. Ces balises sont obligatoires.

guide de conception de formulaires en HTML avec traitementPHP, ergonomie, accessibilitéLe formulaire est un moyen de faire interagir le visiteur avec votre site. Moteur de recherche, espace de contact ou encore forum de discussion, nombreuses sont ses applications. Comment les concevoir et les traiter ?

Cet article explique :• Comment écrire un formulaire en HTML avec des notions de

sémantique, ergonomie et accessibilité.• Une méthode de traitement via le langage PHP.• Des moyens de sécuriser des formulaires.

Ce qu'il faut savoir :• Écrire une page HTML, en doctype HTML ou XHTML (cet article se-

ra basé sur l’HTML Strict, mais le principe est le même en XHTML).• Débugger un script PHP et raisonner pas à pas.• Quelques configurations serveur (droits d’écriture, configura-

tion PHP) pour les téléchargements de fichiers.• Des notions de méthodes de conception (p.ex. MVC) non

abordées ici afin de l’optimiser pour votre site.

Page 31: Zend Framework PHP 01 2011

Formulaire en HTML

www.phpsolmag.org ��

signer quelqu’un. Et de la même façon, utiliser un type checkbox pour demander plusieurs informations sur un même thème (films préférés …).

Il y a également la balise <select> qui permet de créer un menu déroulant. Cette balise se couple à deux autres sous-balises :

• Les balises <option> qui sont les items du menu déroulant.

• Les balises <optgroup> qui permettent de hiérar-chiser visuellement les <option> (Cf. Figure 2).

Balises d’actionEncore une fois, la balise <input> est retrouvée dans cette catégorie :

• <input type="button"> pour créer un bouton gé-nérique,

• <input type="reset"> pour créer un bouton qui réinitialise le formulaire (aux valeurs par défaut des champs),

• <input type="submit"> pour exécuter le formu-laire, c’est-à-dire envoyer au paramètre action les données collectées.

La balise <form> accepte plusieurs attributs :

• Un attribut id permettant de l’identifier de manière unique dans la page HTML.

• Un attribut action qui est l’adresse de la ressource où sera envoyé le formulaire. Dans le cadre de cet article, nous mettrons une page PHP.

• Un attribut method qui peut prendre deux valeurs, POST ou GET.

• GET passe les données du formulaire en texte dans l’adresse du navigateur.

• POST les passe en caché ; c’est donc plus esthéti-que. POST permet également d’envoyer un fichier.

• Un attribut enctype pour l’encodage des données du formulaire, qui peut être omis dans le cas de textes simples mais qui devient obligatoire dès l’at-tachement d’un fichier, pour spécifier que le conte-nu que le formulaire envoi est de plusieurs natu-res.

Remarque : en écriture XHTML Strict, les attributs sont écrits en minuscules et leurs valeurs sont entourées de guillemets doubles.

Balises de division visuelleLa principale balise pour regrouper visuellement des champs est la balise <fieldset>. Graphiquement, el-le produit sur le navigateur une bordure (dont les pro-priétés sont ajustables via CSS) qui entoure tous les champs qu’elle contient. Cette balise est doublée d’une balise <legend> pour donner un titre à cette zone de champs (cf. Figure 1).

Balises de saisie de texteCes balises servent àę envoyer des données fournies par le visiteur.

Le <textarea> permet d’envoyer un texte multiligne tandis que le <input type="texte"> permet d’envoyer une ligne simple.

On trouve également le <input type="hidden"> qui permet d’envoyer un contenu textuel caché (utile pour passer du contenu qui n’a pas besoin d’être sé-curisé de page en page par exemple). Sans oublier le <input type="file"> qui permet l’envoi d’un fichier.

Balises de choixNous y retrouvons le <input> avec deux types parti-culiers :

• La checkbox, case à cocher, pour proposer un choix à réponses multiples.

• Le type radio pour proposer une réponse unique parmi un choix multiple.

Il est tout à fait logique d’utiliser un type radio pour la civilité : Monsieur, Madame ou Mademoiselle pour dé-

Figure 1. Regroupement logique des champs de formulaire en différents fieldset

Figure 2. Classement hiérarchique des options d’un menu Select

Page 32: Zend Framework PHP 01 2011

�/�0����

Fiche technique

Informations communes à toutes les balisesChaque balise peut présenter une valeur par défaut avec le paramètre value=’’votre valeur par défaut ici’’. Dans un textarea, la value ne pouvant pas contenir (ou restituer) plusieurs lignes, cet attribut n’est pas dis-ponible. Le textarea a donc une balise fermante pour délimiter le texte (cf. Listing 1).

Pour les boutons, la value est le texte affiché visuel-lement.

Pour les menus déroulants, l’attribut value doit se placer dans chaque <option>. Des attributs disabled ou readonly permettent respectivement de désactiver ce champ ou de le mettre en lecture seule. La donnée ne sera alors pas envoyée au traitement.

nommage des balisesLe but du formulaire est de le traiter. Pour cela, il faut pouvoir récupérer le contenu de chaque item envoyé au serveur. C’est là qu’intervient le nommage des ba-lises.

Chaque balise présente un attribut name qui est le nom de la future variable que le serveur va créer pour stocker le contenu envoyé.

Par exemple <input type="text" name="prenom"> créera une variable nommée prenom sur le serveur et cette variable contiendra le prénom saisi par l’utili-sateur !

L’attribut name des balises est une suite de caractè-res qui répond aux règles suivantes :

• Il doit commencer par une lettre ou un underscore.• Il ne peut pas contenir d’espaces, de signe de

ponctuation ou autre caractères que les lettres non accentuées et chiffres.

• Il est sensible à la casse (prenom sera différent de Prenom).

Partie HTML : ergonomie et accessibilitéSi vous avez suivi cet article depuis le début, des as-tuces ergonomiques ont été diffusées dans les bali-ses : optgroup pour les menus déroulants, fieldset/legend pour démarquer les zones.

Afin d’apporter un peu plus de confort à votre visi-teur, d’autres astuces peuvent être utilisées :

1. L’utilisation des tabindex qui sont des attributs à valeurs numérique. Le tabindex permet de définir une suite de champs qui seront activés lorsque l’utilisateur pressera le bouton tabulation (Cf. Listing 2).

Quel que soit l’ordre de ces balises dans le code source, ou même leur position dans la page HTML, le prénom sera toujours activé après le nom, premier champ du formulaire activé.

2. L’utilisation d’étiquettes : par défaut, un champ de formulaire est un objet (au sens programmation du terme) et lorsque vous créez un <input type="text" name="nom" tabindex="1"> vous créez en réalité un objet contenant du texte. Mais sans lire le nom, on ne sait pas nativement à quoi ce champ sert. Bien sûr, vous serez vite tenté d’écrire ce qu’il y a dans le Listing 3.

Ce qui n’est pas faux visuellement, mais qui présen-te tout de même une lacune sémantiquement parlant. En effet, bien que le champ et le texte qui le précède soient dans le même paragraphe, ils ne sont pas reliés pour autant. Pour les relier, vous devez mettre une éti-quette qui englobera le tout (Listing 4).

Vous pouvez aussi utiliser un ID sur l’input et le dé-clarer dans le label si vous devez séparer les deux élé-ments (cas d’un tableau par exemple). Voir Listing 5.

Vous remarquerez que l’input a maintenant un attri-but ID qui correspond au for du label.

Maintenant le texte Votre nom ici et l’input sont sé-mantiquement reliés !

Pour le confort de l’utilisateur, il pourra cliquer sur la légende du champ (Votre nom ici) et son curseur sera directement dans le bon champ !

3. L’utilisation d’attributs Javascript : cette méthode permet de mettre une classe CSS particulière lorsque l’utilisateur clique sur le champ (couleur de fond dif-férente par exemple) et une autre couleur lorsqu’il le quitte.

Listing 1. Écriture d’un textarea

<textarea name="MaZoneDeTexte">le texte par défaut ici</textarea>

Listing 2. Insertion d’attribut TabIndex dans un champ de formulaire

<input type="text" name="nom" tabindex="1"> <input type="text" name="prenom" tabindex="2">

Listing 3. Une erreur à éviter

<p>Votre nom ici : <input type="text" name="nom" tabindex="1"></p>

Listing 4. La balise <label> permet de lier logiquement le champ à sa légende

<p><label>Votre nom ici : <input type="text" name="nom" tabindex="1"></label></p>

Listing 5. Label englobant la légende d’un champ et le reliant à ce dernier, avec champ positionné ailleurs dans la page

<table><tr><td><label for="champNom">Votre nom ici :</label></td><td><input type="text" name="nom" tabindex="1" id="champNom"></td></tr></table>

Listing 6. Récupération de variables : checkboxes

$ _ POST['nameBleu'] => on$ _ POST['nameVert'] => on

Page 33: Zend Framework PHP 01 2011

Formulaire en HTML

www.phpsolmag.org ��

Ainsi chaque balise de formulaire peut se voir do-tée de l’attribut onfocus (focus sur le champ, champ activé) et onblur (champ désactivé). Le menu dérou-lant <select> a en plus un attribut onchange qui per-met d’exécuter une action Javascript quand l’utilisa-teur change d’item choisi.

L’accessibilité est une méthode de conception vi-sant à permettre l’accès aux informations selon plusieurs chemins, pour des personnes handica-pées moteur, malvoyantes, ou aveugles. Un formu-laire présentant des label lors d’une lecture par un synthétiseur vocal permettra de lire à voix haute le contenu du label dès que la personne a le focus sur le champ.

Partie PHPUne fois votre formulaire HTML écrit, affiché chez le vi-siteur, il faut maintenant le traiter, c’est-à-dire exécuter l’action que vous avez prévue.

Le traitement de formulaire en PHP peut se décou-per en plusieurs phases :

1. Récupération des variables du formulaire.2. Sécurisation des variables.3. Exécution du traitement proprement dit.4. Message récapitulatif envoyé en HTML si besoin.

Ces étapes ne sont pas une méthode particulière, mais un simple moyen de résumer (arbitrairement) la chrono-logie des étapes.

1. Récupération des variablesA chaque chargement de page, PHP crée (entre

autre) des variables (super globales) que sont $_POST, $_GET et $_FILES. Ce sont des tableaux associatifs (liste de clés paires => valeur).

Si votre formulaire a pour méthode method="get" alors c'est $_GET qui sera rempli. Autrement, c’est $_POST.

$_FILES est rempli lorsque vous avez mis un champ <input type=’’file’’> (téléchargement de fichier).

Enfin, chaque clé du tableau associatif porte le nom (name) du champ de formulaire. Par exemple si en HTML on a :

<input type="text" name="prenom">. Avec un formulaire passé en method="post", on aura $_POST['prenom'] qui contiendra ce que le visiteur a sai-si. Pour un formulaire passé en get, on aurait utilisé $_GET['prenom'].

Attention aux checkbox qui renvoient soit on comme valeur si la case est cochée, soit qui n’existent pas en

PHP. Par exemple, supposons 3 cases à cocher : bleu, rouge, vert avec pour name respectifs : nameBleu, nameRouge, nameVert. Si le visiteur choisit bleu et vert, alors on aura (Listing 6).

(mais $_POST['nameRouge'] n’existera pas)

2. Sécurisation des variablesCette étape est très importante. Elle permet de

s’assurer que les variables ne contiennent pas un contenu qui pourrait occasionner des dégâts (cf. §sé-curité).

Plein de méthodes existent pour sécuriser des va-riables : le transtypage (intval, abs, sprintf) ou les re-quêtes préparées ou encore l’échappement complet des caractères (mysql_escape_strings, mysql_real_escape_strings), ou encore les expressions ra-tionnelles (regexp) sont les solutions les plus commu-nément utilisées. Une variable non sécurisée est une potentielle faille de sécurité ! Toutes les variables doi-vent être sécurisées côté serveur (PHP). Il n’y a aucu-ne sécurité en Javascript, celui-ci pouvant être désac-tivé sur le client.

3. Exécution du traitement proprement ditCette partie permet de faire ce que vous attendez

réellement de votre formulaire : inscrire un nouvel abonné (requêtes SQL), envoyer un email, effectuer une recherche dans un fichier ou une base de don-nées…

4. Message récapitulatifVotre email nous est bien parvenu, aucune répon-

se n’a été trouvée pour l’article que vous avez deman-dé… sont autant d’indications pour indiquer au visiteur que sa demande est finie, réussie, ou tout autre point d’avancement. Cette étape peut ne pas exister dans le cadre de formulaires plus complexes (sondage multi-pages, etc.).

Formulaire et sécuritéComme dit précédemment, la sécurité est primordia-le. La notion la plus importante est de retenir que toute donnée venant d’un visiteur est potentielle-ment vérolée. Il faut tout revérifier au niveau du trai-tement.

Figure 3. Injection SQL : le fait d’avoir mis en commentaire une partie de la requête simplifie la connexion

Figure 4. Injection d’emails : voici le résultat du mail envoyé. La victime recevra le mail, mais elle ne sera pas la seule

Page 34: Zend Framework PHP 01 2011

�/�0����

Fiche technique

Il n’y a aucune sécurité en HTML ou en Javascript : ce sont des langages s’exécutant sur le navigateur Web du visiteur et celui-ci a tout pouvoir dessus. 15% des in-ternautes naviguent d’ailleurs sans Javascript !

N’oubliez pas que le Javascript ne doit pas être in-trusif mais une aide pratique pour faire des vérifications qui, de toute façon, seront refaites dans le traitement du formulaire.

Enfin, les tableaux POST/GET étant créés par envoi de données, il faut vérifier ce que vous recevez.

Voici quelques failles de sécurité bien connues.

L’injection sQLConsiste à utiliser une variable pour y placer du code SQL. Sans protection, la requête modifiée peut s’avérer destructrice…

L’injection d’emailsCas typique des pages de formulaire de contact. Un champ type texte demande l’email du visiteur et cette va-

leur est ensuite mise dans les headers du mail. Si un visi-teur injecte un Cc ou un Bcc (Carbon Copy ou Blind Car-bon Copy) votre formulaire peut devenir un nid à spam (cf. Figure 4).

L’exécution de code sourceVous proposez de télécharger, pour un CV par exemple, la photo du candidat. Une image non vérifiée peut, si les droits sur le serveur ne sont pas bons, donner lieu à une exécution de code source malicieux (cf. Figure 5).

MATTHIeu LACROIXL’auteur est ingénieur systèmes et réseaux dans une PME parisien-ne, en charge d’un parc de cent cinquante machines sous Windows (XP, 7), Linux (Red Hat, Debian) ainsi que des serveurs Windows 2008, HyperV, SAN.Il développe également des solutions back-office/intranet en tant qu’entrepreneur depuis quatre ans (http://www.newslettux.fr/ pré-senté dans un précédent numéro de PHP Solutions).

Figure 5. Un exemple d’avatar en .JPG d’un hackeur, l’entête du fichier contient les informations .JPG et le reste, par du code malicieux, donne des informations

Sur Internet

• http://www.phpsecure.info/ – Tutoriaux en ligne pour sé-curiser des scripts PHP,

• http://www.alsacreations.com/ – Aide HTML, CSS.

Page 35: Zend Framework PHP 01 2011

Formulaire en HTML

www.phpsolmag.org �5

Page 36: Zend Framework PHP 01 2011

1/201136

Pour les débutants

Dans l’article précédent sur le langage de mani-pulation des données, vous avez appris à in-sérer, modifier et supprimer des données d’une

base. Dans ce numéro, vous allez apprendre à extraire un sous-ensemble d’informations des tables.

Pour appliquer les notions présentées, vous devez utiliser un serveur de bases de données MySQL, de préférence la version 5, un serveur web avec PHP ver-sion 5 et le client graphique phpMyAdmin. Les distribu-tions XAMPP (Windows, Linux, Mac OS), WAMP (Win-dows), EasyPHP (Windows) ou MAMP (Mac OS) vous fourniront l’environnement de travail nécessaire.

Les requêtes présentées peuvent être testées via une console SQL ou en mode graphique dans phpMyAdmin.

Dans cet article, nous allons utiliser l’exemple d’une bibliothèque privée dont le schéma a été présenté dans un article paru dans le magazine précédent (N°11/2010 - SQL : langage de manipulation des données). Les don-nées insérées dans les tables auteur et livre sont celles figurant dans les tableaux 1 et 2.

Sélectionner les donnéesLa commande SQL SELECT suivie du caractère * permet d’extraire toutes les données d’une table :

SELECT * FROM nom _ table;Par exemple, pour afficher toutes les lignes de toutes les colonnes de la table auteur (tableau 1), il faut utiliser la requête suivante :

SELECT * FROM auteur;

Trier les donnéesPar défaut, les lignes extraites sont affichées dans l’or-dre d’insertion. La clause ORDER BY suivie d'une ou plu-sieurs colonnes permet de faire un tri sur ces colonnes. Par défaut, elle trie par ordre croissant (ASC), mais la condition DESC permet un tri décroissant. La clause OR-DER BY est toujours placée en fin d’instruction.

SELECT * FROM nom _ table ORDER BY col1 [ASC | DESC][, col2 [ASC | DESC], …];

L’instruction suivante trie les informations de la table auteur par ordre alphabétique sur la colonne nom :

SELECT * FROM auteur ORDER BY nom;

Si plusieurs colonnes sont citées après la clause ORDER BY, le tri sera d’abord effectué sur la première colon-ne renseignée, puis sur la deuxième, etc. Par exemple pour trier la table auteur suivant leurs noms dans l’or-dre croissant, puis suivant leurs prénoms dans l’ordre décroissant, il faut utiliser la commande :

SELECT * FROM auteur ORDER BY nom ASC, prenom DESC;

Sélectionner un sous-ensemble de colonnesIl est possible d’afficher un sous-ensemble de colonnes d’une table en effectuant une projection. Celle-ci est ob-tenue en indiquant une liste de colonnes devant la clau-se FROM, en les séparant par des virgules. Derrière

SQL : extraire des donnéesLes bases de données sont très utilisées dans les applications Web. La création, l’interrogation et la manipulation des données de la base sont réalisées en SQL. Dans cet article, vous apprendrez à extraire des données d’une table et à les trier avec SQL.

Cet article explique :• Comment extraire et trier des données.

Ce qu’il faut savoir :• Aucun prérequis.

Page 37: Zend Framework PHP 01 2011

sQL select

www.phpsolmag.org ��

le FROM sera indiquée la table concernée. Le résultat d’une projection est une table comportant uniquement les colonnes indiquées. Afin d'éviter l'affichage des dou-blons, il faut utiliser le mot-clé DISTINCT.

SELECT [DISTINCT] col1[, col2, …] FROM nom _table;

L’affichage de tous les livres insérés dans la base, ainsi que leur genre et leur date de parution, triés par ordre de parution (tableau 3), est possible grâce à l’instruction suivante :

SELECT titre, genre, date _ parution FROM livre ORDER BY date _ parution;

Pour afficher les genres présents dans la base, on peut utiliser la requête :

SELECT genre FROM livre;

Cette requête renvoie les genres pour chaque livre insé-ré dans la base. Il apparaîtra donc plusieurs fois ‘roman’ et ‘theatre’. Pour afficher une liste ne comprenant qu’une unique fois chaque genre, il faut utiliser DISTINCT :

SELECT DISTINCT genre FROM livre;

sélectionner un sous-ensemble de lignesLa clause WHERE permet de définir une condition afin de sélectionner un sous-ensemble de lignes d'une ta-ble. Celle-ci est une expression comportant un ou plu-sieurs opérateurs (tableau 4) dont les opérandes sont des noms de colonnes, des fonctions ou des constan-tes. MySQL propose un grand nombre de fonctions sur les dates, les nombres et les chaînes de caractères. La restriction affichera toutes les lignes de la table qui ré-pondent à la condition.

SELECT col1[, col2, ...] FROM nom _ table WHERE condition;

nombresPour indiquer une condition quant à une colonne numé-rique, il est possible d’utiliser des opérateurs relation-nels, logiques, ainsi que les opérateurs BETWEEN ou IN.

L’instruction suivante affiche les livres parus après 1950, triés par date de parution :

SELECT titre, date _ parution FROM livre WHERE date _ parution > 1950 ORDER BY date _parution;

Les opérateurs logiques permettent de combiner des conditions. Par exemple, pour afficher les livres parus entre 1950 et 1980 :

SELECT titre, date _ parution FROM livre WHERE date _ parution >= 1950 AND date _parution <= 1980;

La requête précédente peut également être écrite grâce à l’expression nb BETWEEN min AND max qui retourne vrai si le nombre nb est compris entre les bornes min et max :

SELECT titre, date _ parution FROM livre WHERE date _ parution BETWEEN 1950 AND 1980;

Par contre, pour comparer les champs d’une colonne à une liste, il faut utiliser l’expression nb IN (val1[, val2, …]) qui retourne vrai si nb appartient à une des valeurs indiquées.

L’instruction suivante permet d’afficher seulement les livres parus en 2008 ou en 2010 :

SELECT titre, date _ parution FROM livre WHERE date _ parution IN (2008,2010);

Chaînes de caractèresLa restriction peut porter sur des chaînes de caractères. Par exemple, pour afficher tous les romans :

SELECT titre, genre FROM livre WHERE genre = 'roman';

L’expression ch IN (val1[, val2, …]) fonctionne aussi pour les chaînes. Ainsi, l’instruction suivante per-met d’afficher les romans et les livres historiques :

SELECT titre, genre FROM livre WHERE genre IN ('roman','historique');

Il est également possible d’effectuer des comparaisons sur des chaînes en utilisant l’opérateur LIKE. L’expres-sion chaine LIKE motif retourne vrai si la chaîne in-diquée correspond au motif spécifié. Le motif peut être composé de lettres et/ou de symboles : le % représente

Figure 1. Extraire des données depuis phpMyAdmin

Page 38: Zend Framework PHP 01 2011

�/�0����

Pour les débutants

Tableau 1. Contenu de la table AUTEUR

id_auteur nom prenom date_naissance� Follett Ken ����-0�-05

� Dickens Charles ����-0�-0�

� Tolkien J. R. R. ����-0�-0�

� Molière Jean Baptiste ����-0�-�5

5 Herbouiller Sophie NULL

� Massonaud Christophe NULL

Tableau 2. Contenu de la table LIVRE

isbn titre genre date_parution langue nb_pages preface code_zone���-5-5���5-5 Fall of giants historique �0�0 anglais �55 oui c�0

�5�-5-�5���-0 Un bunker à la Baule roman �00� francais ��� non c�0

��0-�-0���5-5 Le bourgeois gentilhomme theatre ���0 francais �5� NULL NULL

�5�-5-55��5-� Le seigneur des anneaux fantastique ��5� francais ��� non c�

5��-5-�5���-� David Copperfield roman ��50 anglais �5� oui s�

��0-�-0���5-� Amphitryon theatre ���� francais ��0 oui c��

Tableau 3. Sélection et tri d’un sous-ensemble de colonnes.

titre genre date_parutionAmphitryon theatre ����

Le bourgeois gentilhomme theatre ���0

David Copperfield roman ��50

Le seigneur des anneaux fantastique ��5�

Un bunker à la Baule roman �00�

Fall of giants historique �0�0

Tableau 4. Opérateurs

Opérateurs SQLOpérateurs arithmétiques+ Addition

- Soustraction

* Multiplication

/ Division

Opérateurs logiques

AND Et (x AND y vrai uniquement si x vrai et y vrai)OR Ou (x OR y faux uniquement si x faux et y faux)NOT Non

Opérateurs relationnels

= Egal à

<> Différent de

< Inférieur à

<= Inférieur ou égal à

> Supérieur à

>= Supérieur ou égal à

Autres opérateurs

chaine LIKE motif Vrai si la chaine suit le motif

exp IN (val�, val�, ...) Vrai si l’expression appartient à une des valeurs

exp BETWEEN min AND max Vrai si l’expression est comprise entre les deux bornes

exp IS NULL Vrai si l’expression a la valeur NULL

exp IS NOT NULL Vrai si l’expression n’a pas la valeur NULL

Page 39: Zend Framework PHP 01 2011

sQL select

www.phpsolmag.org ��

n’importe quelle chaîne et le _ représente un unique ca-ractère quelconque.

L’instruction suivante affiche tous les livres dont le code zone commence par un ‘C’ suivi de deux caractè-res quelconques (dans le tableau 2, les livres qui ont les codes zone : c10, c18 et c20) :

SELECT titre FROM livre WHERE code _ zone LIKE 'c _ _ ';

Par contre, la requête suivante renvoie tous les livres dont le code zone commence par un ‘C’, quel que soit le nombre de caractères (les livres dont le code zone est c10, c18, c20 ou c8) :

SELECT titre FROM livre WHERE code _ zone LIKE 'c%';

Il est possible de définir des conditions sur des co-lonnes de type numérique et alphanumérique dans une même requête. Pour afficher les romans parus après 1950, il faut exécuter :

SELECT titre FROM livre WHERE genre = 'roman' AND date _ parution > 1950;

DatesLa restriction peut porter sur des colonnes de type da-te. Par exemple, pour afficher tous les auteurs nés au XIXème siècle :

SELECT nom FROM auteur WHERE YEAR(date _ naissance) BETWEEN 1800 AND 1899;

La fonction MySQL YEAR retourne l’année de la date pas-sée en argument. La fonction MONTH retourne un numé-ro entre 1 et 12 correspondant au mois. Pour lister les auteurs nés en juin :

SELECT nom FROM auteur WHERE MONTH(date _ naissance) = 6;

nuLLL’opérateur IS NULL permet de sélectionner les lignes dont les champs ne sont pas renseignés. Pour extraire les lignes dont le code zone n’a pas été défini :

SELECT titre FROM livre WHERE code _ zone IS NULL;

L’opérateur inverse serait IS NOT NULL. La requête sui-vante extrait tous les livres dont le code zone est ren-seigné :

SELECT titre FROM livre WHERE code _ zone IS NOT NULL;

Créer des colonnes dérivéesIl est également possible d’extraire des informations de manière personnalisée en créant des colonnes qui ne sont pas présentes dans la base. Ces co-lonnes peuvent prendre des valeurs retournées par des fonctions ou des calculs. Ces colonnes ne sont pas ajoutées dans la base de données, elles appa-raissent uniquement lors de l'affichage du résultat de la requête. Par exemple, on peut vouloir extraire l’ancienneté d’un livre (tableau 5). Pour ce faire, il suffit de retrancher la date de parution à la date du jour :

SELECT titre, YEAR(NOW())-date _ parution FROM livre ORDER BY titre;

La requête retourne un tableau de deux colon-nes dont la première est intitulée ‘titre’ et l’autre ‘YEAR(NOW())-date_parution’. Pour renommer cet-te colonne (tableau 6), il faut utiliser un alias (AS).. Il est aussi possible de faire un tri sur cette nouvelle colonne :

SELECT titre, (YEAR(NOW())-date _ parution) AS anciennete FROM livre ORDER BY anciennete;

Tableau 5. Colonne dérivée et tri

titre YEAR(NOW())-da-te_parution

Amphitryon ���

David Copperfield ���

Fall of giants �

Le bourgeois gentilhomme ���

Le seigneur des anneaux 5�

Un bunker à la Baule �

Tableau 6. Colonne dérivée avec alias et tri

titre anciennete

Fall of giants �

Un bunker à la Baule �

Le seigneur des anneaux 5�

David Copperfield ���

Le bourgeois gentilhomme ���

Amphitryon ���

Tableau 7. Regroupement de données

ecrivain anneeK. Follett ����

C. Dickens ����

J. Tolkien ����

J. Molière ����

S. Herbouiller NULL

C. Massonaud NULL

Page 40: Zend Framework PHP 01 2011

�/�0���0

Pour les débutants

La requête suivante crée une colonne 'ecrivain' qui contient la liste des auteurs comprenant seulement la première lettre de leur prénom suivi d’un point et de leur nom (format : ‘C. Dickens’) ainsi qu’une colonne contenant leur année de naissance, comme dans le tableau 7 :

SELECT CONCAT(SUBSTRING(prenom,1,1),'. ',nom) AS ecrivain, YEAR(date _ naissance) AS annee FROM auteur;

extraire des données avec phpMyAdminL’interface Web phpMyAdmin permet d’extraire des don-nées via l’utilisation d’un formulaire. Une fois la base sé-lectionnée sur la page d’accueil, il faut choisir la table concernée dans le cadre de gauche. Un clic sur l’icô-ne Rechercher dans le menu du cadre de droite per-met d’afficher le formulaire d’extraction (figure 1). Il est proposé une liste de conditions spécifiques à chaque champ. Sous le bouton Options, une liste à choix mul-tiples permet de réaliser une projection en choisissant quelles colonnes devront s’afficher. La soumission du formulaire génère automatiquement la requête, l’affiche et l’envoie à MySQL. Sur la figure 1, il a été rempli pour répondre à la requête :

SELECT titre, date _ parution FROM livre WHERE date _ parution > 1950 ORDER BY date _parution;

Cependant, cette interface ne permet pas actuellement de faire de conditions multiples sur un champ. Il est no-tamment impossible de donner deux bornes à une date de parution.

ConclusionVous avez appris dans cet article à extraire et trier des données provenant d’une table. Grâce aux connais-sances acquises dans cette série d’articles, vous êtes à présent à même de réaliser des bases de données simples, d’y insérer des données et de les interroger. L’article sur les jointures vous permettra d’interroger plusieurs tables simultanément à la suite de quoi vous verrez comment vous connecter à la base via PHP avec PDO.

CILIA MAuRO, MAgALI COnTensInCilia Mauro est gestionnaire de bases de données et développeur d’applications web au CNRS. Elle enseigne les bases de données et PHP à l’université.Contact : [email protected] Contensin est chef de projet en développement d’applica-tions au CNRS. Elle enseigne depuis plus de dix ans le développe-ment d’applications web à l’université et est l’auteur de nombreux articles sur le développement web en PHP.Contact : http://magali.contensin.online.fr

Sur Internet

• http://www.phpmyadmin.net - phpMyAdmin• http://www.mysql.fr – MySQL,

Tableau 8. Quelques fonctions MySQL prédéfinies

Fonctions MySQL

Fonctions sur les datesDATEDIFF(date�, date�) Retourne le nombre de jour entre date� et date�

MONTH(date) Retourne le mois de la date

NOW() Retourne la date courante

YEAR(date) Retourne l’année de la date

Fonctions sur les chaînes de caractères

CONCAT(ch�, ch�, ...) Retourne la concaténation des chaînes ch�, ch�, ...

LENGTH(ch) Retourne la longueur de la chaîne ch

SUBSTRING(ch, pos, lg) Retourne la sous-chaîne de ch débutant à l’indice pos et de taille lg

TRIM(ch) Retourne la chaîne ch sans les espaces ni à droite ni à gauche

Fonctions mathématiques

MOD(nb�,nb�) Retourne le reste de la division de nb� par nb� (modulo)

SQRT(nb) Retourne la racine carrée de nb

TRUNCATE(nb,dec) Retourne nb tronqué en fonction de la decimale dec

Page 41: Zend Framework PHP 01 2011

www.phpsolmag.org ��

Pour les débutants

Dans les articles précédents vous avez appris les bases du langage SQL. Vous êtes capables de réaliser des bases de données simples, d’y in-

sérer des données et de les interroger. Dans l’article précédent (dans ce numéro : SQL : extraire des don-nées), vous avez vu comment extraire des données d’une table. Cet article explique comment interroger plusieurs tables en même temps.

Afin d’appliquer les prochaines notions, il est né-cessaire que vous utilisiez l’environnement de travail présenté dans l’article précédent. L'interface Web phpMyAdmin utilisée jusqu’ici ne permet pas de gé-nérer graphiquement des jointures, aussi les requê-tes suivantes devront être testées via une console SQL.

Cet article sera illustré par l'exemple d'une bibliothè-que privée (Figure 1) dont les données insérées dans les tables auteur et livre sont les mêmes que dans l’arti-cle sur l’extraction des données. Les données des tables zone et ecrit apparaissent dans les tableaux 1 et 2.

Jusqu’à présent, vous avez extrait des données d’une seule table. Parfois il est nécessaire de faire une extraction sur plusieurs tables. Par exemple, pour afficher tous les livres présents dans une pièce don-née, une solution est de passer par deux requêtes. La première extrait les codes zone d’intérêt, ici pour une chambre :

SELECT code _ zone FROM zone WHERE piece = 'chambre';

sQL : les jointuresLes bases de données sont très utilisées dans les applications Web. La création, l’interrogation et la manipulation des données de la base sont réalisées en SQL. Dans cet article, vous apprendrez à extraire des données issues de plusieurs tables avec SQL.

Cet article explique :• Comment extraire des données de plusieurs tables simulta-

nément.

Ce qu’il faut savoir :• Avoir lu l'article SQL : extraire des données (de ce même nu-

méro).

Figure 1. Schéma de la base de données biblio

Page 42: Zend Framework PHP 01 2011

�/�0����

sQL Jointure

La seconde utilise le résultat de la première pour affi-cher les titres des livres présents dans cette pièce :

SELECT titre FROM livre WHERE code _ zone IN ('c10','c18','c20','c8');

Une solution plus efficace de procéder est de regrou-per les données des tables livre et zone grâce à une jointure.

Après avoir présenté le produit cartésien sur lequel reposent les jointures, vous verrez quels types de join-tures existent et comment les utiliser.

Produit cartésienLa jointure consiste à faire le produit cartésien de deux tables puis de restreindre les lignes grâce à une condi-tion. La syntaxe JOIN avec ON permet d’indiquer le type de jointure (interne ou externe, détaillées plus tard) et la condition :

SELECT col1[, col2, …] FROM table1 [NATURAL] [LEFT|RIGHT] JOIN table2 ON condition;

Le produit cartésien de deux tables est l’ensemble de tous les couples possibles entre les lignes de ces ta-bles. Il associe à chaque ligne de la table livre la pre-mière ligne de la table zone, puis il associe à chaque li-gne de la table livre la seconde ligne de la table zone, etc. Le tableau 3 montre le produit cartésien d’un sous-ensemble de colonnes des tables livre et zone. Pour l’afficher, il suffit d’extraire les deux tables sans condi-tion de jointure :

SELECT livre.titre, livre.date _ parution, livre.code _ zone AS code1, zone.code _ zone AS code2, zone.piece FROM livre JOIN zone;

Le caractère point permet d'indiquer la table d'où pro-vient la colonne et évite les ambiguïtés possibles quant à savoir s'il s'agit du code_zone de la table livre ou de celui de la table zone.

Pour diminuer le nombre de caractère d'une requê-te, il est possible de donner un alias aux tables. Dans la requête suivante, équivalente à la précédente, la table livre a été renommée en L et la table zone en Z :

SELECT L.titre, L.date_parution, L.code_zone AS code1, Z.code_zone AS code2, Z.piece FROM livre L JOIN zone Z;

Jointure interneLe produit cartésien du tableau 3 a généré toutes les possibilités de couples, les seuls qui nous intéressent sont ceux dont les codes zone sont identiques (lignes du tableau 3 marquées d'un | dans la dernière colon-ne). Pour afficher tous les livres présents dans une piè-

ce, il faut donc indiquer que la comparaison porte sur la colonne code_zone de la table livre et la colonne code_zone de la table zone :

SELECT L.titre, L.date _ parution, L.code _ zone AS code1, Z.code _ zone AS code2, Z.piece FROM livre L JOIN zone Z ON L.code _ zone = Z.code _ zone;

Cette requête est une jointure interne. Elle s'exerce par défaut si le type de jointure n'est pas précisé ou si IN-NER JOIN est utilisé. Ce type de jointure, le plus fré-quemment rencontré, suit la syntaxe :

SELECT col1[, col2, …] FROM table1 [INNER] JOIN table2 ON condition;

La requête de l'exemple retourne cinq lignes. Le livre non référencé (code_zone à NULL) n'apparaît pas.

Pour afficher tous les livres présents dans une cham-bre, il suffit d'ajouter une restriction à la requête :

SELECT L.titre, L.date_parution, L.code_zone AS code1, Z.code_zone AS code2, Z.piece FROM livre L JOIN zone Z ON L.code_zone = Z.code_zone WHERE Z.piece = 'chambre';

Une notation plus ancienne peut être rencontrée pour réaliser une jointure :

SELECT col1[, col2, …] FROM table1, table2 WHERE condition;

La condition de jointure est spécifiée après la clause WHERE et les tables sont listées après le FROM séparées

Tableau 1. Contenu de la table zone

code_zone piece meublec�0 chambre armoire en pin

c�� chambre armoire en pin

c�0 chambre bibliothèque noire

c� chambre commode

s�� salon bibliothèque noire

s� salon buffet en chêne

Tableau 2. Contenu de la table ecrit

isbn id_auteur���-5-5���5-5 �

5��-5-�5���-� �

�5�-5-55��5-� �

��0-�-0���5-� �

��0-�-0���5-5 �

�5�-5-�5���-0 5

�5�-5-�5���-0 �

Page 43: Zend Framework PHP 01 2011

www.phpsolmag.org ��

Pour les débutants

Tableau 3. Produit cartésien d’un sous-ensemble de colonnes des tables livre et zone

titre date_parution code1 code2 pieceFall of giants �0�0 c�0 c�0 chambre

Le seigneur des anneaux ��5� c� c�0 chambre

Amphitryon ���� c�� c�0 chambre

Le bourgeois gentilhomme ���0 NULL c�0 chambre

David Copperfield ��50 s� c�0 chambre

Un bunker à la Baule �00� c�0 c�0 chambre I

Fall of giants �0�0 c�0 c�� chambre

Le seigneur des anneaux ��5� c� c�� chambre

Amphitryon ���� c�� c�� chambre I

Le bourgeois gentilhomme

���0 NULL c�� chambre

David Copperfield ��50 s� c�� chambre

Un bunker à la Baule �00� c�0 c�� chambre

Fall of giants �0�0 c�0 c�0 chambre I

Le seigneur des anneaux ��5� c� c�0 chambre

Amphitryon ���� c�� c�0 chambre

Le bourgeois gentilhomme

���0 NULL c�0 chambre

David Copperfield ��50 s� c�0 chambre

Un bunker à la Baule �00� c�0 c�0 chambre

Fall of giants �0�0 c�0 c� chambre

Le seigneur des anneaux ��5� c� c� chambre I

Amphitryon ���� c�� c� chambre

Le bourgeois gentilhomme ���0 NULL c� chambre

David Copperfield ��50 s� c� chambre

Un bunker à la Baule �00� c�0 c� chambre

Fall of giants �0�0 c�0 s�� salon

Le seigneur des anneaux ��5� c� s�� salon

Amphitryon ���� c�� s�� salon

Le bourgeois gentilhomme ���0 NULL s�� salon

David Copperfield ��50 s� s�� salon

Un bunker à la Baule �00� c�0 s�� salon

Fall of giants �0�0 c�0 s� salon

Le seigneur des anneaux ��5� c� s� salon

Amphitryon ���� c�� s� salon

Le bourgeois gentilhomme ���0 NULL s� salon

David Copperfield ��50 s� s� salon I

Un bunker à la Baule �00� c�0 s� salon

Tableau 4. Afficher tous les livres et leur zone s’ils sont référencés

titre date_parution code1 code2 piece

Fall of giants �0�0 c�0 c�0 chambre

Le seigneur des anneaux ��5� c� c� chambre

Amphitryon ���� c�� c�� chambre

Le bourgeois gentilhomme ���0 NULL NULL NULL

David Copperfield ��50 s� s� salon

Un bunker à la Baule �00� c�0 c�0 chambre

Page 44: Zend Framework PHP 01 2011

�/�0����

sQL Jointure

par des caractères virgules. La requête précédente peut être réécrite :

SELECT L.titre, L.date_parution, L.code_zone AS code1, Z.code_zone AS code2, Z.piece FROM livre L , zone Z WHERE L.code_zone = Z.code_zone AND Z.piece = 'chambre';

La syntaxe avec JOIN et ON est plus claire car elle per-met de différencier les conditions de jointure des restric-tions, mais les résultats des deux sont équivalentes.

Jointure naturelle.Lorsque les colonnes de la condition de jointure ont le même nom dans chaque table, la jointure peut être réa-lisée automatiquement en utilisant le mot-clé NATURAL devant le type de jointure. La requête, qui affiche les livres et la pièce dans laquelle ils sont stockés, aurait pu être écrite :

SELECT L.titre, L.code _ zone AS code1, Z.code _ zone AS code2, Z.piece FROM livre L NATURAL JOIN zone Z;

Jointure externeLa jointure interne ne permet pas d’obtenir les livres qui n’ont pas été rangés dans une pièce, c’est à dire ceux dont le code zone a la valeur NULL. Seules les lignes qui ont une correspondance dans l’autre table sont affichées. Les jointures externes (OUTER JOIN) permettent d’afficher des lignes qui n’ont pas forcément de correspondance :

SELECT col1[, col2, …] FROM table1 [NATURAL] [LEFT|RIGHT] [OUTER] JOIN table2 ON condition;

Jointure gaucheAfin d'afficher tous les livres, référencés ou non, il faut réa-liser une jointure externe gauche (LEFT [OUTER] JOIN) :

SELECT L.titre, L.date_parution, L.code_zone AS code1, Z.code_zone AS code2, Z.piece FROM livre L LEFT JOIN zone Z ON L.code_zone = Z.code_zone;

La requête retourne les lignes de la jointure interne plus les lignes de la table de gauche qui n'ont pas de corres-pondance dans la table de droite (zone). Dans ce cas, les colonnes de la table de droite comporteront la valeur NULL (tableau 4).

Les colonnes de la condition de jointure ayant le mê-me nom, il est possible de faire une jointure naturelle externe :

SELECT L.titre, L.date _ parution, L.code _zone AS code1, Z.code _ zone AS code2, Z.piece FROM livre L NATURAL LEFT JOIN zone Z;

Jointure droitePour afficher toutes les zones et les livres qu’elles contiennent, s’il y en a, il faut utiliser une jointure ex-terne droite :

SELECT L.titre, L.date _ parution, L.code _zone AS code1, Z.code _ zone AS code2, Z.piece FROM livre L RIGHT JOIN zone Z ON L.code _zone = Z.code _ zone;

La jointure retourne toutes les lignes de la jointure in-terne plus les lignes de la table de droite (zone) qui n'ont pas de correspondance dans la table livre (ta-bleau 5).

Une jointure droite peut s’écrire sous la forme d’une jointure gauche en inversant l’ordre des tables. La re-quête suivante est équivalente à la jointure droite ci-dessus (tableau 5) :

SELECT L.titre, L.date _ parution, L.code _zone AS code1, Z.code _ zone AS code2, Z.piece FROM zone Z LEFT JOIN livre L ON L.code _zone = Z.code _ zone;

Tableau 5. Afficher toutes les zones et les livres qu’elles contiennent

titre date_parution code1 code2 piece

Un bunker à la Baule

�00� c�0 c�0 chambre

Amphitryon ���� c�� c�� chambre

Fall of giants �0�0 c�0 c�0 chambre

Le seigneur des anneaux

��5� c� c� chambre

NULL NULL NULL s�� salon

David Copper-field

��50 s� s� salon

Figure 2. Organigramme

Page 45: Zend Framework PHP 01 2011

www.phpsolmag.org �5

Pour les débutants

Jointure complèteLa norme SQL définit des jointures externes complètes qui retournent toutes les lignes de la table de gauche et de la table de droite (FULL JOIN). Celles-ci ne sont pas implé-mentées dans MySQL mais peuvent être obtenues grâce à une union du résultat de deux requêtes (LEFT + RIGHT) :

SELECT col1[, col2, …] FROM table1 LEFT JOIN table2 ON conditionUNIONSELECT col1[, col2, …] FROM table1 RIGHT JOIN table2 ON condition;

Pour effectuer une union, il faut que les deux requêtes renvoient le même nombre de colonnes et que celles-ci soient du même type.

Jointure sur trois tablesIl est parfois nécessaire de faire des jointures sur plus de deux tables. Dans l’exemple, pour afficher les livres et le nom de leurs auteurs (tableau 6), il faut interroger trois tables. La table ecrit permet d’associer un ou plu-sieurs auteurs à un livre. La requête s’écrit donc :

SELECT L.titre, A.nom FROM livre L JOIN ecrit E ON L.isbn = E.isbn JOIN auteur A ON E.id _auteur = A.id _ auteur;

Les jointures sont faites successivement. Le résultat de la jointure entre les tables livre et ecrit est joint à la table auteur.

Comme précédemment, les conditions de jointure portent sur des colonnes de même nom, il est donc pos-sible d’écrire :

SELECT L.titre, A.nom FROM livre L NATURAL JOIN ecrit NATURAL JOIN auteur A;

Auto-jointureDans certains cas, il peut s’avérer nécessaire de joindre une table à elle-même. Par exemple pour retrouver des liens de parenté entre des personnes ou afficher le su-périeur hiérarchique d’un groupe d’employés (Figure 2). Cet exemple sera utilisé pour présenter l’auto-jointure.

Une table stocke tous les employés d’une entreprise et comporte une colonne chef qui référence l’identifiant d’un des employés de la même table, ou NULL si l’em-ployé n’a pas de supérieur hiérarchique (tableau 7). Pour afficher la liste de tous les employés et de leur chef, il faut faire une jointure interne. Comme elle portera sur la mê-me table, il faut lui donner deux alias différents :

SELECT E.id, E.nom, C.nom AS chef FROM employe E JOIN employe C ON E.chef = C.id;

La requête retourne cinq lignes et n’affiche pas les em-ployés qui n’ont pas de supérieur hiérarchique (dans l’exemple, celui dont l’id est 1). Pour l’afficher (ta-bleau 8), il faut faire une jointure externe :

SELECT E.id, E.nom, C.nom AS chef FROM employe E LEFT JOIN employe C ON E.chef = C.id;

ConclusionVous avez appris dans cet article à extraire des don-nées provenant de plusieurs tables. Grâce aux connais-sances acquises dans cette série d'articles, vous êtes à présent à même de réaliser des bases de données simples, d'y insérer des données et de les interroger. Le prochain article vous montrera comment interroger une base de données via PHP avec PDO.

Tableau 6. Titre des livres et leurs auteurs

titre nomFall of giants Follett

Le seigneur des anneaux Tolkien

Amphitryon Molière

Le bourgeois gentilhomme Molière

David Copperfield Dickens

Un bunker à la Baule Herbouiller

Un bunker à la Baule Massonaud

Tableau 7. Contenu de la table employe

id nom chef� X NULL

� Y �

� Z �

� A �

5 B �

� C �

Tableau 8. Affichage de tous les employés et de leur chef

id nom chef� X NULL

� Y X

� Z X

� A Y

5 B Y

� C Z

CILIA MAuRO, MAgALI COnTensInCilia Mauro est gestionnaire de bases de données et développeur d’applications web au CNRS. Elle enseigne les bases de données et PHP à l’université.Contact : [email protected] Contensin est chef de projet en développement d’applications au CNRS. Elle enseigne depuis plus de dix ans le déve-loppement d’applications web à l’université et est l’auteur de nomb-reux articles sur le développement web en PHP.Contact : http://magali.contensin.online.fr

Page 46: Zend Framework PHP 01 2011

�/�0����

Pour les débutants

AP NEWWEBSITE_203X293 19/05/10 10:59 Page 1

Page 47: Zend Framework PHP 01 2011

www.phpsolmag.org ��

Pour les débutants