Development

Documentation/fr_FR/book/1.0/trunk/02-Exploring-Symfony-s-Code (diff)

You must first sign up to be able to contribute.

Changes between Version 11 and Version 12 of Documentation/fr_FR/book/1.0/trunk/02-Exploring-Symfony-s-Code

Show
Ignore:
Author:
forresst (IP: 82.253.9.157)
Timestamp:
07/02/08 00:09:30 (9 years ago)
Comment:

Respect mardown, comparaison avec l'original et correctifs en tout genre

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/fr_FR/book/1.0/trunk/02-Exploring-Symfony-s-Code

    v11 v12  
    1515 
    1616Chapitre 2 – L'exploration du code de Symfony 
    17 ============================================= 
    18  
    19 Au premier regard le code de Symfony peut sembler déroutant. Il est réparti sur plusieurs répertoires, comporte beaucoup de scripts comme des classes PHP ou du HTML, et quelque fois un mélange des deux. Il y est aussi fait référence à des classes que vous aurez du mal à retrouver dans cette arborescence étendue sur six niveaux. Mais une fois compris le pourquoi du comment de cette apparente complexité, tout vous semblera tellement naturel que vous n’aurez pas envie d’échanger votre Symfony pour autre chose (pas même contre un baril d’Ariel). Ce chapitre a pour but de détailler le mécanisme de Symfony et de vous ôter vos dernières peurs. 
     17==================================== 
     18 
     19Au premier regard le code de Symfony peut sembler déroutant. Il est réparti sur plusieurs répertoires, comporte beaucoup de scripts comme des classes PHP ou du HTML, et quelque fois un mélange des deux. Il y est aussi fait référence à des classes que vous aurez du mal à retrouver dans cette arborescence étendue sur six niveaux. Mais une fois compris le pourquoi du comment de cette apparente complexité, tout vous semblera tellement naturel que vous n’aurez pas envie d’échanger votre symfony pour autre chose (pas même contre un baril d’Ariel). Ce chapitre a pour but de détailler le mécanisme de symfony et de vous ôter vos dernières peurs. 
    2020 
    2121Le modèle MVC  
    22 ------------- 
     22--------------- 
    2323 
    2424Symfony est basé sur le modèle classique de conception web connu sous le nom architecture [MVC] [1] (Modèle – Vue – Contrôleur), composé de trois parties : 
    2525 
    26   * Le Modèle, qui représente le comportement de l’application, sa logique de métier. 
    27   * La Vue, qui représente l’interface web proprement dite. 
    28   * Le Contrôleur, qui prend en charge la gestion des évènements et commande la mise à jour de la Vue ou du Modèle. 
     26  * Le Modèle, qui représente le comportement de l’application, sa logique de métier. 
     27  * La Vue, qui représente l’interface web proprement dite. 
     28  * Le Contrôleur, qui prend en charge la gestion des évènements et commande la mise à jour de la Vue ou du Modèle. 
    2929 
    3030Le schéma 2-1 illustre l’architecture [MVC] [1] 
    3434*Schéma 2-1 L'architecture [MVC] [1]* 
    3535 
    36 ![Le modèle MVC](http://www.symfony-project.org/images/book/trunk/F0201.png "Le modèle MVC") 
     36![Le modèle MVC](/images/book/F0201.png "Le modèle MVC") 
    3737 
    3838### L’architecture MVC 
    4545 
    4646 
    47 *Listing 2-1 - Un script standard* 
     47Listing 2-1 - Un script standard 
    4848 
    4949    [php] 
    6161    <html> 
    6262      <head> 
    63         <title>Liste des Messages</title> 
     63        <title>List of Posts</title> 
    6464      </head> 
    6565      <body> 
    66        <h1>Liste des Messages</h1> 
     66       <h1>List of Posts</h1> 
    6767       <table> 
    6868         <tr><th>Date</th><th>Title</th></tr> 
    8888    ?> 
    8989 
    90  
    9190C’est rapide à écrire et à exécuter mais difficile à maintenir. Les principaux problèmes de ce code sont : 
    9291 
    93   * Pas de contrôle d’erreur (que se passe-t-il si la connexion échoue ?) 
    94   * La syntaxe s’appuie sur du PHP et du HTML entremêlés. 
    95   * Le code n’est adapté qu’à la base de données MySQL. 
     92  * Pas de contrôle d’erreur (que se passe-t-il si la connexion échoue ?). 
     93  * La syntaxe s’appuie sur du PHP et du HTML entremêlés. 
     94  * Le code n’est adapté qu’à la base de données MySQL. 
    9695 
    9796#### Isoler la présentation 
    9998Sur le listing 2-1, l’utilisation des ordres `echo`  et `printf` complexifie la lisibilité du code et tout changement de présentation, via une modification du source HTML, devient périlleux. Par conséquent nous diviserons ce script en deux parties. La première contiendra le code PHP et la logique de métier qui seront déplacés dans le script du contrôleur, comme indiqué dans l’exemple 2-2 
    10099 
    101 *Exemple 2-2 La partie contrôleur dans `index.php`.* 
     100Exemple 2-2 La partie contrôleur dans `index.php` 
    102101 
    103102    [php] 
    126125     ?> 
    127126 
    128 Le code HTML, contenant la syntaxe PHP dédiée à la présentation, sera stocké dans le script de vue comme indiqué dans l’exemple 2-3 
    129  
    130 *Exemple 2-3 – La partie vue, dans `view.php`.* 
     127Le code HTML, contenant la syntaxe PHP dédiée à la présentation, sera stocké dans le script de vue comme indiqué dans l’exemple 2-3. 
     128 
     129Exemple 2-3 – La partie vue, dans `view.php` 
    131130 
    132131    [php] 
    133132    <html> 
    134133      <head> 
    135         <title>Liste de Messages</title> 
     134        <title>List of Posts</title> 
    136135      </head> 
    137136      <body> 
    138         <h1>Liste de Messages</h1> 
     137        <h1>List of Posts</h1> 
    139138        <table> 
    140139          <tr><th>Date</th><th>Title</th></tr> 
    149148    </html> 
    150149 
    151 Pour qu’un script de vue soit de bonne qualité, il doit contenir le moins de code PHP possible et aucun ordres PHP encapsulant des balises HTML de manière à être compréhensible par un graphiste démuni de connaissances en PHP. 
    152 Les ordres les plus communs dans un script vue sont `echo`, `if/endif`, `foreach/endforeach`. 
     150Pour qu’un script de vue soit de bonne qualité, il doit contenir le moins de code PHP possible et aucun ordres PHP encapsulant des balises HTML de manière à être compréhensible par un graphiste démuni de connaissances en PHP. Les ordres les plus communs dans un script vue sont echo, if/endif, foreach/endforeach. 
    153151 
    154152Toute la logique de traitement des données est placée dans le script Contrôleur et ne contient que la syntaxe PHP, sans aucun code HTML. Dans l’idéal, il faut pouvoir réutiliser le même contrôleur pour une présentation complètement différente comme une impression PDF ou un fichier XML. 
    156154#### Isoler la manipulation des données 
    157155 
    158 La majeure partie du code d’un script contrôleur est dédiée à la manipulation des données. Mais que se passerait-il si vous aviez besoin de la même liste de messages pour un autre contrôleur, comme pour la gestion d’un flux RSS par exemple ? Comment faire si vous souhaitez conserver toutes les requêtes de base de données dans un même fichier pour éviter de dupliquer le code ? Que faire si vous décidez de changer la structure de la base de données et que la table `posts`  devient ` weblog_post` ? N’allez-vous pas un jour migrer de PostgreSQL à MySQL ? Pour permettre toutes ces opérations nous allons devoir placer la manipulation des données dans un autre script appelé modèle (cf exemple 2-4) 
    159  
    160 *Exemple 2-4 La partie modèle, dans `model.php`.* 
     156La majeure partie du code d’un script contrôleur est dédiée à la manipulation des données. Mais que se passerait-il si vous aviez besoin de la même liste de messages pour un autre contrôleur, comme pour la gestion d’un flux RSS par exemple ? Comment faire si vous souhaitez conserver toutes les requêtes de base de données dans un même fichier pour éviter de dupliquer le code ? Que faire si vous décidez de changer la structure de la base de données et que la table `post`  devient `weblog_post` ? N’allez-vous pas un jour migrer de PostgreSQL à MySQL ? Pour permettre toutes ces opérations nous allons devoir placer la manipulation des données dans un autre script appelé modèle (cf exemple 2-4). 
     157 
     158Exemple 2-4 La partie modèle, dans `model.php` 
    161159 
    162160    [php] 
    184182      return $posts; 
    185183    } 
     184 
    186185    ?> 
    187186 
    188187L’exemple 2-5 montre le contrôleur modifié. 
    189188 
    190 *Exemple 2-5 la partie contrôleur, dans `index.php`.* 
     189Exemple 2-5 la partie contrôleur, dans `index.php` 
    191190 
    192191    [php] 
    247246    } 
    248247 
    249 *Listing 2-7 - Accès aux données du modèle* 
     248Listing 2-7 - Accès aux données du modèle 
    250249 
    251250    [php] 
    270269      return $posts; 
    271270    } 
     271 
    272272    ?> 
    273273 
    279279#### La partie Vue 
    280280 
    281 La vue aussi peut faire l’objet d’une séparation de code. Une page contient souvent des éléments communs à toute l’application comme l’entête, le pied de page, la charte graphique, les principes de navigations etc… Seule le contenu de la page est appelé à changer. Ainsi on peut distinguer deux parties dans la vue : la maquette (layout) et le gabarit (template). 
    282 La maquette est généralement globale à l’application ou à un groupe de pages et le gabarit met en forme les données fournies par le contrôleur. Une troisième partie est la vue logique (ou simplement vue) qui permet aux deux premières de travailler de concert. 
    283 En appliquant ces principes, le listing 2-3 peut être séparé en trois parties comme le montrent les listings 2-8, 2-9 et 2-10 
    284  
    285 *Listing 2-8 La partie gabarit de la vue, dans `mytemplate.php`.* 
    286  
    287     [php] 
    288     <h1>Liste de messages</h1> 
     281La vue aussi peut faire l’objet d’une séparation de code. Une page contient souvent des éléments communs à toute l’application comme l’entête, le pied de page, la charte graphique, les principes de navigations etc… Seule le contenu de la page est appelé à changer. Ainsi on peut distinguer deux parties dans la vue : la maquette (layout) et le gabarit (template). La maquette est généralement globale à l’application ou à un groupe de pages et le gabarit met en forme les données fournies par le contrôleur. Une troisième partie est la vue logique (ou simplement vue) qui permet aux deux premières de travailler de concert. En appliquant ces principes, le listing 2-3 peut être séparé en trois parties comme le montrent les listings 2-8, 2-9 et 2-10 
     282 
     283Listing 2-8 La partie gabarit de la vue, dans `mytemplate.php` 
     284 
     285    [php] 
     286    <h1>List of Posts</h1> 
    289287    <table> 
    290288    <tr><th>Date</th><th>Title</th></tr> 
    292290      <tr> 
    293291        <td><?php echo $post['date'] ?></td> 
    294        <td><?php echo $post['title'] ?></td> 
     292        <td><?php echo $post['title'] ?></td> 
    295293      </tr> 
    296294    <?php endforeach; ?> 
    297295    </table> 
    298296 
    299 *Listing 2-9 La vue logique de la vue* 
    300  
    301     [php] 
    302     <?php 
    303   
    304     $title = 'Liste de messages'; 
     297Listing 2-9 La vue logique de la vue 
     298 
     299    [php] 
     300    <?php 
     301 
     302    $title = 'List of Posts'; 
    305303    $content = include('mytemplate.php'); 
     304 
    306305    ?> 
    307306 
    308 *Listing 2-10 La partie maquette de la vue* 
    309  
    310     [php] 
    311  
     307Listing 2-10 La partie maquette de la vue 
     308 
     309    [php] 
    312310    <html> 
    313311      <head> 
    314        <title><?php echo $title ?></title> 
     312        <title><?php echo $title ?></title> 
    315313      </head> 
    316314      <body> 
    319317    </html> 
    320318 
    321  
    322 #### Action et contrôleur principal (front controller). 
     319#### Action et contrôleur principal (front controller) 
    323320 
    324321Dans les exemples précédents, le contrôleur ne fait pas grand chose, mais dans une application web réelle, il est sûrement celui qui a le plus de travail. De plus, la plupart des contrôleurs partagent en grande partie les mêmes actions comme la gestion des requêtes, la sécurité, la configuration de l’application etc… C’est pourquoi les contrôleurs sont plus souvent représentés par un contrôleur principal unique à l’application et par les actions, qui ne contiennent que le code contrôleur spécifique à certaines pages. 
    325322 
     323L'un des grands avantages d'un contrôleur frontal est qu'il offre un point d'entrée unique pour toute l'application. Si vous décidez de fermer l'accès à l'application, vous aurez seulement besoin de modifier le script de contrôleur frontal. Dans une application sans un contrôleur frontal, chaque contrôleur doit être désactivé. 
     324 
    326325#### Orienté objet. 
    327326 
    333332 
    334333>**TIP** 
    335 >Si vous voulez approfondir vos connaissances sur les motifs de conception pour le web en orienté objet, procurez-vous le livre Patterns of Entreprise Application Architecture de Martin Fowler (Addison-Wesley, ISBN : 0-32112-742-0). Les exemples sont en Java ou C#, mais restent compréhensibles pour un développeur PHP. [Sur Amazon](http://www.amazon.fr/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_11_1/402-5852976-8124116?ie=UTF8&qid=1180975022&sr=11-1 Sur Amazon.com) 
     334>Si vous voulez approfondir vos connaissances sur les motifs de conception pour le web en orienté objet, procurez-vous le livre Patterns of Entreprise Application Architecture de Martin Fowler (Addison-Wesley, ISBN : 0-32112-742-0). Les exemples sont en Java ou C#, mais restent compréhensibles pour un développeur PHP. 
    336335 
    337336### L’implémentation [MVC] [1] de Symfony 
    338337 
    339 Revenons à notre liste de messages. Combien de couches faut-il donc implémenter pour obtenir cette simple page ? Nous avons identifié les éléments illustrés par le schéma 2-2 : 
    340  
    341    * Niveau Modèle 
    342       * Abstraction de données 
    343       * Accès aux données 
    344    * Niveau Vue 
    345       * Vue (logique de vue) 
    346       * Gabarit 
    347       * La maquette 
    348    * Le niveau Contrôleur  
    349      * Le contrôleur principal 
    350      * Les actions 
    351  
    352 Sept scripts ! Beaucoup de fichiers à ouvrir et à modifier pour chaque nouvelle page ! 
    353 Cependant, Symfony rend les choses faciles car tout en prenant le meilleur de l’architecture [MVC] [1], il l’implémente de manière à rendre le développement rapide et aisé. 
     338Revenons à notre liste de messages. Combien de couches faut-il donc implémenter pour obtenir cette simple page ? Nous avons identifié les éléments illustrés par le schéma 2-2: 
     339 
     340  * Niveau Modèle 
     341    * Abstraction de données 
     342    * Accès aux données 
     343  * Niveau Vue 
     344    * Vue (logique de vue) 
     345    * Gabarit 
     346    * La maquette 
     347  * Le niveau Contrôleur  
     348    * Le contrôleur principal 
     349    * Les actions 
     350 
     351Sept scripts ! Beaucoup de fichiers à ouvrir et à modifier pour chaque nouvelle page! Cependant, Symfony rend les choses faciles car tout en prenant le meilleur de l’architecture [MVC] [1], il l’implémente de manière à rendre le développement rapide et aisé. 
    354352 
    355353Tout d’abord, le contrôleur principal et la maquette sont communs à toute l’application. Vous pouvez en avoir plusieurs mais un seul de chaque est nécessaire. Le contrôleur principal est un composant pur [MVC] [1], ce qui veut dire que vous n’aurez jamais à le coder, Symfony le générera pour vous. 
    359357Enfin, la logique de vue peut s’appuyer sur un simple fichier de configuration, sans avoir besoin de programmation. 
    360358 
    361 *Schéma 2-2 Le processus Symfony* 
    362  
    363 ![Diagramme de flux de Symfony](http://www.symfony-project.org/images/book/trunk/F0202.png "Diagramme de flux de Symfony") 
    364  
    365 Il en résulte que notre liste de messages ne requiert plus que trois fichiers pour fonctionner comme le montrent les listings 2-11, 2-12, 2-13 
    366  
    367 *Listing 2-11 Actions de `list` de `myproject/apps/myapp/modules/weblog/actions/actions.class.php`.* 
     359Schéma 2-2 Le processus Symfony 
     360 
     361![Diagramme de flux de Symfony](/images/book/F0202.png "Diagramme de flux de Symfony") 
     362 
     363Il en résulte que notre liste de messages ne requiert plus que trois fichiers pour fonctionner comme le montrent les listings 2-11, 2-12, 2-13. 
     364 
     365Listing 2-11 Action de `list` de `myproject/apps/myapp/modules/weblog/actions/actions.class.php` 
    368366 
    369367    [php] 
    371369    class weblogActions extends sfActions 
    372370    { 
    373       public function executeListe() 
    374         { 
    375         $this->messages = MessagePeer::doSelect(new Criteria()); 
    376         } 
    377     } 
     371      public function executeList() 
     372      { 
     373        $this->posts = PostPeer::doSelect(new Criteria()); 
     374      } 
     375    } 
     376 
    378377    ?> 
    379378 
    380 *Listing 2-12 Gabarit de `liste`, de `myproject/apps/myapp/modules/weblog/templates/listeSuccess.php`.* 
    381  
    382     [php] 
    383     <h1>Liste de messages</h1> 
     379Listing 2-12 Template de `liste`, de `myproject/apps/myapp/modules/weblog/templates/listSuccess.php` 
     380 
     381    [php] 
     382    <h1>List of Posts</h1> 
    384383    <table> 
    385     <tr><th>Date</th><th>Titre</th></tr> 
    386     <?php foreach ($messagess as $message): ?> 
     384    <tr><th>Date</th><th>Title</th></tr> 
     385    <?php foreach ($posts as $post): ?> 
    387386      <tr> 
    388         <td><?php echo $message->getDate() ?></td> 
    389         <td><?php echo $message->getTitre() ?></td> 
     387        <td><?php echo $post->getDate() ?></td> 
     388        <td><?php echo $post->getTitle() ?></td> 
    390389      </tr> 
    391390    <?php endforeach; ?> 
    392391    </table> 
    393392 
    394 *Listing 2-13 Vue de `liste`, de `myproject/apps/myapp/modules/weblog/config/view.yml`.* 
     393Listing 2-13 Vue de `liste`, de `myproject/apps/myapp/modules/weblog/config/view.yml` 
    395394 
    396395    listSuccess: 
    397       metas: { title: Liste de messages } 
    398   
     396      metas: { title: List of Posts } 
     397 
    399398De plus, vous allez aussi devoir définir une maquette, comme le montre le listing 2-14.  Elle sera régulièrement réutilisée. 
    400399 
    401 *Listing 2-14 – Maquette de `liste`, dans `myproject/apps/myapp/templates/layout.php`.* 
     400Listing 2-14 – Maquette de `liste`, dans `myproject/apps/myapp/templates/layout.php` 
     401 
    402402    [php] 
    403403    <html> 
    410410    </html> 
    411411 
    412 Voilà donc tout ce qui vous est nécessaire. Ce code a exactement le même effet que celui écrit en PHP standard vu plus haut sur le listing 2-1. Faire fonctionner tous les composants ensemble n'est pas de votre ressort et est géré pas Symfony. Si vous inspectez le code vous verrez que le développement de la liste de messages en architecture [MVC] [1] ne requiert pas plus de temps, ni de code que l'écriture en PHP standard. 
    413 Cependant, cela vous apporte de grands avantages comme une organisation plus claire du code, la possibilité de le réutiliser facilement, de la flexibilité, des possibilités de deboggage, une configuration aisée, l'abstraction de données, la réécriture d'URL, le multi-environnement et encore beaucoup d'outils de développement. 
     412Voilà donc tout ce qui vous est nécessaire. Ce code a exactement le même effet que celui écrit en PHP standard vu plus haut sur le listing 2-1. Faire fonctionner tous les composants ensemble n'est pas de votre ressort et est géré pas Symfony. Si vous inspectez le code vous verrez que le développement de la liste de messages en architecture [MVC] [1] ne requiert pas plus de temps, ni de code que l'écriture en PHP standard. Cependant, cela vous apporte de grands avantages comme une organisation plus claire du code, la possibilité de le réutiliser facilement, de la flexibilité, des possibilités de deboggage, une configuration aisée, l'abstraction de données, la réécriture d'URL, le multi-environnement et encore beaucoup d'outils de développement. 
    414413 
    415414#### Le noyau de Symfony 
    417416L'implémentation [MVC] [1] de Symfony utilise plusieurs classes que vous rencontrerez plusieurs fois dans ce livre : 
    418417 
    419   * ‘sfController` est la classe contrôleur. Elle interprète les requêtes et les transmet aux actions. 
    420   * ‘sfRequest` conserve les éléments des requêtes comme les paramètres, les cookies, les entêtes, etc ... 
    421   * ‘sfResponse` contient les entêtes et le contenu des réponses. C'est l'objet qui peut éventuellement être converti en HTML et renvoyé à l'utilisateur. 
    422   * Le contexte (récupéré par `sfContext::getInstance()`) conserve une référence de chaque objet du noyau et de la configuration courante. Il est accessible de n'importe où. 
     418  * `sfController` est la classe contrôleur. Elle interprète les requêtes et les transmet aux actions. 
     419  * `sfRequest` conserve les éléments des requêtes comme les paramètres, les cookies, les entêtes, etc ... 
     420  * `sfResponse` contient les entêtes et le contenu des réponses. C'est l'objet qui peut éventuellement être converti en HTML et renvoyé à l'utilisateur. 
     421  * Le contexte (récupéré par `sfContext::getInstance()`) conserve une référence de chaque objet du noyau et de la configuration courante. Il est accessible de n'importe où. 
    423422 
    424423Vous pourrez en apprendre plus sur ces objets au chapitre 6. 
    430429 
    431430L'organisation du code 
    432 ---------------------- 
     431----------------- 
    433432 
    434433Maintenant que vous connaissez les différents composants de Symfony vous vous demandez sûrement comment ils sont agencés. Symfony organise le code par projets et chaque projet possède une arborescence standard. 
    435434 
    436 ### La structure des projets: applications, modules et actions. 
     435### La structure des projets: applications, modules et actions 
    437436 
    438437Avec Symfony, un projet est un ensemble de services et opérations réunis sous un nom de domaine donné, partageant le même modèle objet. 
    442441Chaque application est un ensemble d'un ou plusieurs modules. Un module correspond généralement à une page ou un groupe de pages traitant du même sujet. Par exemple, vous pouvez avoir les modules `accueil`, `articles`, `aide`, `panier`, `compte` etc ... 
    443442 
    444 Les modules contiennent des actions qui peuvent être utilisées au sein de ce module. Par exemple, un `panier` peut comporter les actions `ajouter`, `afficher`, `mettre à jour` etc ... Généralement, les actions peuvent être décrites par un simple verbe. Une action peut être vue comme une page particulière d'une application web classique, à ceci près que deux actions peuvent avoir comme résultat la même page. (par exemple, ajouter une commentaire dans un message d'un weblog réaffiche ce message avec le nouveau commentaire.) 
     443Les modules contiennent des actions qui peuvent être utilisées au sein de ce module. Par exemple, un `panier` peut comporter les actions `ajouter`, `afficher`, `mettre à jour` etc ... Généralement, les actions peuvent être décrites par un simple verbe. Une action peut être vue comme une page particulière d'une application web classique, à ceci près que deux actions peuvent avoir comme résultat la même page. (par exemple, ajouter une commentaire dans un message d'un weblog réaffiche ce message avec le nouveau commentaire). 
    445444 
    446445>**TIP** 
    447 >Si cette organisation est trop étoffée pour un premier projet, il est possible de regrouper toutes les actions dans un seul module. Quand l'application deviendra plus complexe, il sera encore temps d'organiser les actions dans des modules séparés. Comme indiqué dans le chapitre 1, réécrire le code pour améliorer son organisation ou sa lisibilité tout en conservant son comportement est appelé le *refactoring*, et vous ferez souvent ça lorsque vous appliquerez les principes du RAD. 
     446>Si cette organisation est trop étoffée pour un premier projet, il est possible de regrouper toutes les actions dans un seul module. Quand l'application deviendra plus complexe, il sera encore temps d'organiser les actions dans des modules séparés. Comme indiqué dans le chapitre 1, réécrire le code pour améliorer son organisation ou sa lisibilité tout en conservant son comportement est appelé la refactorisation, et vous ferez souvent ça lorsque vous appliquerez les principes du RAD. 
    448447 
    449448Le schéma 2-3 vous montre un exemple d'organisation de code pour un weblog avec une structure projet/application/module/action. Notez que l'arborescence réelle du projet différera de l'organisation montrée dans ce schéma. 
    450449 
    451 *Schéma 2-3 Exemple d'organisation de code.* 
    452  
    453 ![Exemple d'organisation du code](http://www.symfony-project.org/images/book/trunk/F0203.png "Exemple d'organisation du code") 
    454  
     450Schéma 2-3 Exemple d'organisation de code 
     451 
     452![Exemple d'organisation du code](/images/book/F0203.png "Exemple d'organisation du code") 
    455453 
    456454### L'arborescence 
    458456La plupart des projets web partagent un certains nombres d'éléments comme : 
    459457 
    460   * une base de données comme MySQL ou PostgreSQL 
    461   * des fichiers statiques (HTML, images, fichiers JavaScript, feuilles de styles etc ...) 
    462   * des fichiers ajoutés par les utilisateurs ou administrateurs 
    463   * des classes et librairies PHP 
    464   * des librairies externes (scripts externes) 
    465   * des fichiers batch (des scripts exécutés en ligne de commande ou via les tâches planifiées) 
    466   * des fichiers journaux (traces laissées par une application et/ou le serveur) 
    467   * des fichiers de configuration. 
     458  * une base de données comme MySQL ou PostgreSQL 
     459  * des fichiers statiques (HTML, images, fichiers JavaScript, feuilles de styles etc ...) 
     460  * des fichiers ajoutés par les utilisateurs ou administrateurs 
     461  * des classes et librairies PHP 
     462  * des librairies externes (scripts externes) 
     463  * des fichiers batch (des scripts exécutés en ligne de commande ou via les tâches planifiées) 
     464  * des fichiers journaux (traces laissées par une application et/ou le serveur) 
     465  * des fichiers de configuration 
    468466 
    469467Symfony fournit une arborescence standard de dossiers afin d’organiser le contenu de façon logique et conformément aux choix de l’architecture (modèles [MVC] [1] regroupement projet/application/module). 
    497495 
    498496Le tableau 2-1 décrit le contenu de ces répertoires 
    499 *Tableau 2-1 Répertoires racines* 
    500  
    501  
    502 <table style="border:1px solid;"><tr><td>Répertoire </td><td> Description 
    503 </td></tr><tr><td><tt>apps/</tt>    </td><td> Contient un répertoire par applications du projet (communément <tt>frontend</tt> et <tt>backend</tt> pour le front et le back office) 
    504 </td></tr><tr><td><tt>batch/</tt>   </td><td> Contient les scripts PHP appelés par une ligne de commande ou un planificateur de tâches 
    505  
    506 </td></tr><tr><td><tt>cache/</tt>   </td><td> Contient le cache de la configuration et (si vous l’activez) le cache des actions et des gabarits du projet. Le cache (décrit au chapitre 12) utilise ces fichiers pour améliorer les temps de réponses des requêtes. Chaque applications y aura donc un sous-répertoire contenant des processus PHP ou HTML prétraité. 
    507 </td></tr><tr><td><tt>config/</tt>  </td><td> Contient la configuration générale du projet 
    508 </td></tr><tr><td><tt>data/</tt>    </td><td> Tout ce qui est relatif aux bases de données est conservé ici : le schéma de la base de donné, les fichiers SQL de création etc … 
    509 </td></tr><tr><td><tt>doc/</tt>     </td><td> Contient la documentation du projet y compris votre propre documentation et celle générée par PHPdoc 
    510 </td></tr><tr><td><tt>lib/</tt>     </td><td> Ce répertoire est réservé aux classes et librairies extérieures. Vous pouvez-y ajouter du code devant être partagé par toutes vos applications. Le répertoire <tt>model/</tt>contient le modèle objet du projet (cf. Chapitre 8) 
    511  
    512 </td></tr><tr><td><tt>log/</tt>     </td><td> Ici sont conservés les fichiers journaux générés par Symfony. Il peut aussi contenir les journaux du serveur web, des bases de données ou n’importe quels autres fichiers journaux du projet. Symfony crée un fichier journal par application et environnement (cf Chapitre 16) 
    513 </td></tr><tr><td><tt>plugins/</tt> </td><td> Ce répertoire contient les plugins installés pour cette application (cf Chapitre 17) 
    514 </td></tr><tr><td><tt>test/</tt>    </td><td> Il contient des jeux d’essai unitaires et fonctionnels écrit en php et compatibles avec le framework de test de Symfony (cf Chapitre 15). 
    515 </td></tr><tr><td><tt>web/</tt>     </td><td> La racine du serveur web. Seuls les fichiers se trouvant dans ce fichier sont accessible via Internet. 
    516 </td></tr></table> 
    517  
     497 
     498Tableau 2-1 Répertoires racines 
     499 
     500Répertoire | Description 
     501---------- | ------------ 
     502`apps/`    | Contient un répertoire par applications du projet (communément `frontend` et `backend` pour le front et le back office). 
     503`batch/`   | Contient les scripts PHP appelés par une ligne de commande ou un planificateur de tâches. 
     504`cache/`   | Contient le cache de la configuration et (si vous l’activez) le cache des actions et des gabarits du projet. Le cache (décrit au chapitre 12) utilise ces fichiers pour améliorer les temps de réponses des requêtes. Chaque applications y aura donc un sous-répertoire contenant des processus PHP ou HTML prétraité. 
     505`config/`  | Contient la configuration générale du projet. 
     506`data/`    | Tout ce qui est relatif aux bases de données est conservé ici : le schéma de la base de donné, les fichiers SQL de création etc … 
     507`doc/`     | Contient la documentation du projet y compris votre propre documentation et celle générée par PHPdoc. 
     508`lib/`     | Ce répertoire est réservé aux classes et librairies extérieures. Vous pouvez-y ajouter du code devant être partagé par toutes vos applications. Le répertoire `model/` contient le modèle objet du projet (cf. Chapitre 8). 
     509`log/`     | Ici sont conservés les fichiers journaux générés par Symfony. Il peut aussi contenir les journaux du serveur web, des bases de données ou n’importe quels autres fichiers journaux du projet. Symfony crée un fichier journal par application et environnement (cf Chapitre 16). 
     510`plugins/` | Ce répertoire contient les plugins installés pour cette application (cf Chapitre 17). 
     511`test/`    | Il contient des jeux d’essai unitaires et fonctionnels écrit en php et compatibles avec le framework de test de Symfony (cf Chapitre 15). 
     512`web/`     |  La racine du serveur web. Seuls les fichiers se trouvant dans ce fichier sont accessible via Internet. 
    518513 
    519514#### L’arborescence d’une application 
    522517 
    523518    apps/ 
    524       [nom de l’application]
     519      [application name
    525520        config/ 
    526521        i18n/ 
    532527          error.txt 
    533528 
    534 Le tableau 2-2 décrit les répertoires d’une application 
    535  
    536 *Tableau 2-2 Répertoires d’une application* 
    537  
    538 <table style="border:1px solid;"><tr><td>Répertoire </td><td> Description  
    539 </td></tr><tr><td><tt>config/</tt>    </td><td> Contient l’ensemble des fichiers de configuration YAML. Le plus gros de la configuration de l’application se trouve ici mis à part les paramètres par défaut conservé  au sein du framwork lui-même. Remarque : les paramètres par défaut peuvent être écrasés ici si nécessaire. Vous en apprendrez plus sur la configuration d’une application au chapitre 5 
    540 </td></tr><tr><td><tt>I18n/</tt>      </td><td> Contient les fichiers d’internationalisation de l’application, des fichiers de traduction de l’interface la plus part du temps. (Cf Chapitre 13) Vous pouvez vous passer de ces fichiers si vous gérez l’internationalisation pas la base de donnée 
    541 </td></tr><tr><td><tt>lib/</tt>       </td><td> Contient les librairies et les classes spécifiques à l’application 
    542 </td></tr><tr><td><tt>modules/</tt>   </td><td> Contient tous les modules propres à l’application 
    543  
    544 </td></tr><tr><td><tt>templates/</tt> </td><td> Contient tous les gabarits de l’application, ceux partagé par tous les modules. Par défaut, il contient <tt>layout.php</tt> qui est la maquette dans laquelle tous les gabarits sont insérés. 
    545 </td></tr></table> 
    546  
     529Le tableau 2-2 décrit les répertoires d’une application. 
     530 
     531Tableau 2-2 Répertoires d’une application 
     532 
     533Répertoire   | Description 
     534------------ | ----------- 
     535`config/`    | Contient l’ensemble des fichiers de configuration YAML. Le plus gros de la configuration de l’application se trouve ici mis à part les paramètres par défaut conservé  au sein du framwork lui-même. Remarque : les paramètres par défaut peuvent être écrasés ici si nécessaire. Vous en apprendrez plus sur la configuration d’une application au chapitre 5. 
     536`i18n/`      | Contient les fichiers d’internationalisation de l’application, des fichiers de traduction de l’interface la plus part du temps. (Cf Chapitre 13) Vous pouvez vous passer de ces fichiers si vous gérez l’internationalisation pas la base de donnée. 
     537`lib/`       | Contient les librairies et les classes spécifiques à l’application. 
     538`modules/`   |  Contient tous les modules propres à l’application. 
     539`templates/` |  Contient tous les gabarits de l’application, ceux partagé par tous les modules. Par défaut, il contient `layout.php` qui est la maquette dans laquelle tous les gabarits sont insérés. 
    547540 
    548541>**NOTE** 
    549 >Les répertoires `i18/`, `lib/` et `modules/` sont vides pour une nouvelle application. 
    550  
    551 Les classes d’une application ne sont pas capables d’accéder aux méthodes ou attributs d’une tierce application d’un même projet.  
    552 Lorsque vous déciderez de la manière de diviser votre projet en plusieurs applications, vous devrez garder à l’esprit que les liens hypertextes entre ces différentes applications devront être de forme absolue. 
     542>Les répertoires `i18n/`, `lib/` et `modules/` sont vides pour une nouvelle application. 
     543 
     544Les classes d’une application ne sont pas capables d’accéder aux méthodes ou attributs d’une tierce application d’un même projet. Lorsque vous déciderez de la manière de diviser votre projet en plusieurs applications, vous devrez garder à l’esprit que les liens hypertextes entre ces différentes applications devront être de forme absolue. 
    553545 
    554546#### L’arborescence du module 
    559551 
    560552    apps/ 
    561       [nom de l’application]/ 
     553      [application name]/ 
    562554        modules/ 
    563           [nom du module]/ 
     555          [module name]/ 
    564556              actions/ 
    565557                actions.class.php 
    570562              validate/ 
    571563 
    572 Le tableau 2-3 décrit les répertoires du module 
    573  
    574 *Tableau 2-3 Répertoires du module* 
    575  
    576  
    577 <table style="border:1px solid;"><tr><td> Répertoire </td><td>  Description 
    578 </td></tr><tr><td> <tt>actions/</tt>   </td><td>  En règle générale, ce répertoire possède ne contient que la classe <tt>actions.class.php</tt> qui regroupe toutes les actions du modules. Il est aussi possible d’écrire plusieurs actions dans des fichiers séparés 
    579 </td></tr><tr><td> <tt>config/</tt>    </td><td>  Il peut contenir des fichiers de paramétrages locaux pour les modules 
    580  
    581 </td></tr><tr><td> <tt>lib/</tt>       </td><td>  Contient les classes et librairies spécifiques au module 
    582 </td></tr><tr><td> <tt>template/</tt>  </td><td>  Contient les gabarits correspondant aux actions du module. Un gabarit par défaut appelé <tt>indexSucces.php</tt>, est crée par défaut à l’installation du module 
    583 </td></tr><tr><td> <tt>validate/</tt>  </td><td>  Dédié à la configuration des fichiers utilisés par le formulaire de validation (cf Chapitre 10)  
    584 </td></tr></table> 
    585  
    586  
     564Le tableau 2-3 décrit les répertoires du module. 
     565 
     566Tableau 2-3 Répertoires du module 
     567 
     568 
     569Répertoire   | Description 
     570------------ | ------------ 
     571`actions/`   | En règle générale, ce répertoire possède ne contient que la classe `actions.class.php` qui regroupe toutes les actions du modules. Il est aussi possible d’écrire plusieurs actions dans des fichiers séparés 
     572`config/`    | Il peut contenir des fichiers de paramétrages locaux pour les modules 
     573`lib/`       | Contient les classes et librairies spécifiques au module 
     574`template/`  | Contient les gabarits correspondant aux actions du module. Un gabarit par défaut appelé `indexSucces.php`, est crée par défaut à l’installation du module 
     575`validate/`  | Dédié à la configuration des fichiers utilisés par le formulaire de validation (cf Chapitre 10)  
    587576 
    588577>**NOTE** 
    591580#### L’arborescence web 
    592581 
    593 Le dossier web, qui regroupe tous les fichiers accessibles sur le net, n’a que peu de sous-répertoires. 
    594 Le respect de conventions de nommage claires facilitera l’utilisation de ces dossiers dans les gabarits. Voici un exemple de l’arborescence d’un dossier  
    595 web 
     582Le dossier `web`, qui regroupe tous les fichiers accessibles sur le net, n’a que peu de sous-répertoires. Le respect de conventions de nommage claires facilitera l’utilisation de ces dossiers dans les gabarits. Voici un exemple de l’arborescence d’un dossier `web`: 
    596583 
    597584    web/ 
    601588      uploads/ 
    602589 
    603 Par convention, les fichiers statiques sont répartis dans les dossiers décrits par le tableau 2-4 
    604  
    605 *Tableau 2-4 – Arborescence Web classique* 
    606  
    607 <table style="border:1px solid;"><tr><td>Répertoire </td><td> Description 
    608 </td></tr><tr><td><tt>css/</tt>     </td><td> Contient les feuilles de styles avec l’extension <tt>.css</tt> 
    609 </td></tr><tr><td><tt>images/</tt>  </td><td> Contient les images aux formats <tt>.jpg</tt>, <tt>.png</tt> ou <tt>.gif</tt> 
    610  
    611 </td></tr><tr><td><tt>js/</tt>      </td><td> Contient les fichiers <a class="wiki" href="/wiki/JavaScript">JavaScript</a> avec l’extension <tt>.js</tt> 
    612 </td></tr><tr><td><tt>uploads/</tt> </td><td> Doit contenir les images uploadées par l’utilisateur. Même si le dossier contient des images, il est bien distinct du dossier des images afin que la synchronisation des serveurs de développement et de production, n’affecte pas les images uploadées. 
    613 </td></tr></table> 
    614  
     590Par convention, les fichiers statiques sont répartis dans les dossiers décrits par le tableau 2-4. 
     591 
     592Tableau 2-4 – Arborescence Web classique 
     593 
     594Répertoire | Description 
     595---------- | ----------- 
     596`css/`     | Contient les feuilles de styles avec l’extension `.css` 
     597`images/`  | Contient les images aux formats `.jpg`, `.png` ou `.gif` 
     598`js/`      | Contient les fichiers <a class="wiki" href="/wiki/JavaScript">JavaScript</a> avec l’extension `.js` 
     599`uploads/` | Doit contenir les images uploadées par l’utilisateur. Même si le dossier contient des images, il est bien distinct du dossier des images afin que la synchronisation des serveurs de développement et de production, n’affecte pas les images uploadées. 
    615600 
    616601>**NOTE** 
    626611Beaucoup de classes Symfony possèdent un conteneur de paramètres. C’est un moyen simple d’encapsuler un attribut avec des méthodes getter et setter correctes. Par exemple, la classe `sfResponse` possède un conteneur de paramètres que vous pouvez utiliser en appelant la méthode `getParameterHolder()`. Chaque conteneur de paramètres conserve les données comme illustré par le listing 2-15. 
    627612 
    628 *Listing 2-15 Utilisation du conteneur de paramètre de `sfResponse`* 
    629  
    630     [php] 
    631     $response->getParameterHolder()->set(‘foo’, ‘bar’); 
    632     Echo $response->getParameterHolder()-get(‘foo’); 
    633     => ‘bar’ 
    634  
     613Listing 2-15 Utilisation du conteneur de paramètre de `sfResponse` 
     614 
     615    [php] 
     616    $response->getParameterHolder()->set('foo', 'bar'); 
     617    echo $response->getParameterHolder()->get('foo'); 
     618     => 'bar' 
    635619 
    636620La plupart des classes utilisant le conteneur de paramètres se servent de méthodes intermédiaires pour raccourcir le code saisi pour les opérations get/set. Dans le cas de l’objet `sfResponse`, l’opération décrite dans le listing 2-15 peut-être simplifiée comme le montre le listing 2-16 
    637621 
    638 *Listing 2-16 Utilisation des méthodes intermédiaires des conteneurs de paramètres de `sfResponse`* 
    639  
    640     [php] 
    641     $response->setParameter(‘foo’, ‘bar’); 
    642     Echo $response->getParameter(‘foo’); 
    643     => ‘bar’ 
    644  
     622Listing 2-16 Utilisation des méthodes intermédiaires des conteneurs de paramètres de `sfResponse` 
     623 
     624    [php] 
     625    $response->setParameter('foo', 'bar'); 
     626    echo $response->getParameter('foo'); 
     627     => 'bar' 
    645628 
    646629La méthode getter du conteneur de paramètres accepte une valeur par défaut comme second argument ce qui permet un échappement automatique bien plus léger qu’un équivalent réalisé par un codage conditionnel. Le listing 2-17 illustre ce point de vue. 
    647630 
    648 *Listing 2-17 – Utilisation de la valeur par défaut de l’attribut du getter* 
     631Listing 2-17 – Utilisation de la valeur par défaut de l’attribut du getter 
    649632 
    650633    [php] 
    651634    // Le paramètre 'foobar' n’est pas défini, donc le getter renvoie une valeur vide 
    652635    echo $response->getParameter('foobar'); 
    653     => null 
    654   
     636    => null 
     637 
    655638    // Une valeur par défaut peut-être utilisée en ajoutant le getter dans la condition suivante 
    656639    if ($response->hasParameter('foobar')) 
    663646    } 
    664647     => default 
    665   
     648 
    666649    // Mais il est plus rapide d’utiliser le deuxième argument du getter pour cela. 
    667650    echo $response->getParameter('foobar', 'default'); 
    668     => default 
    669  
     651     => default 
    670652 
    671653Les conteneurs de paramètres peuvent aussi supporter les espaces de nommage. Si vous spécifiez un troisième paramètre, il sera interprété comme un espace de nommage et le paramètre sera alors défini uniquement dans cet espace. Le Listing 2-18 illustre ce point. 
    672654 
    673 *Listing 2-18 – Utilisation de l’espace de nommage du conteneur de paramètres de la méthode `sfResponse`* 
    674  
    675     [php] 
    676     $response->setParameter(‘foo’, ‘bar1’) ; 
    677     $response->setParameter(‘foo’, ‘bar2’, ‘my/name/space’); 
    678     Echo $response->getParameter(‘foo’); 
    679     => ‘bar1’ 
    680     Echo $response->getParamater(‘foo’, null, ‘my/name/space’); 
    681     => ‘bar2’ 
    682  
     655Listing 2-18 – Utilisation de l’espace de nommage du conteneur de paramètres de la méthode `sfResponse` 
     656 
     657    [php] 
     658    $response->setParameter('foo', 'bar1'); 
     659    $response->setParameter('foo', 'bar2', 'my/name/space'); 
     660    echo $response->getParameter('foo'); 
     661     => 'bar1' 
     662    echo $response->getParameter('foo', null, 'my/name/space'); 
     663     => 'bar2' 
    683664 
    684665Vous pouvez bien évidemment ajouter un conteneur de paramètres dans vos propres classes pour profiter de cette fonctionnalité. Le listing 2-19 vous explique comment définir une classe avec un conteneur de paramètres. 
    685666 
    686 *Listing 2-19 Ajouter un conteneur de paramètres à une classe* 
     667Listing 2-19 Ajouter un conteneur de paramètres à une classe 
    687668 
    688669    [php] 
    690671    { 
    691672      protected $parameter_holder = null; 
     673 
    692674      public function initialize ($parameters = array()) 
    693675      { 
    695677        $this->parameter_holder->add($parameters); 
    696678      } 
    697   
     679 
    698680      public function getParameterHolder() 
    699681      { 
    702684    } 
    703685 
    704  
    705686### Constantes 
    706687 
    707688Étrangement vous ne trouverez que peu de constantes dans Symfony et ce pour le simple fait qu’il existe une contrainte majeure en PHP : une fois définie, leur valeur devient non modifiable. C’est pour cela que pour remplacer les constantes, Symfony utilise son propre objet de configuration : `sfConfig`. Grace à ses méthodes statiques, vous pouvez atteindre ce paramètre de n’importe où. Le listing 2-20 vous montre comment utiliser l’objet sfConfig. 
    708689 
    709 *Listing 2-20 Utilisation de l’objet `sfConfig` à la place des constantes* 
     690Listing 2-20 Utilisation de l’objet `sfConfig` à la place des constantes 
    710691 
    711692    [php] 
    724705 
    725706    [php] 
    726     Include ‘classes/MyClass.php’
     707    include 'classes/MyClass.php'
    727708    $myObject = new MyClass(); 
    728709 
    729  
    730710Mais au sein de projets volumineux possédant beaucoup de classes et une architecture complexe, se souvenir de tous les fichiers à inclure et de leur chemin devient fastidieux. En proposant la fonction __autoload() –ou la fonction `spl_autoload_register()`), Symfony rend obsolète l’emploi de l’ordre `include`. Vous pouvez alors directement écrire 
    731711 
    732712    [php] 
    733713    $myObject = new MyClass(); 
    734  
    735714 
    736715Dès lors, Symfony recherche la définition de `MyClass` dans tous les fichiers d’extension `.php` présents dans l’un des répertoires `lib/` du projet. S’il la trouve, elle est incluse automatiquement. 
    742721 
    743722Résumé 
    744 ------ 
     723------- 
    745724 
    746725L’usage d’un framework basé sur [MVC] [1] vous oblige à répartir et organiser votre code en accord avec certaines règles précises. Le code de présentation est placé dans la vue, le modèle hérite du code de manipulation de données, et toute la partie gestion des requêtes se retrouve au niveau du contrôleur. Ceci rend les applications s’appuyant sur l’architecture [MVC] [1] à la fois plus simples à utiliser et plus contraignantes. 
    747726 
    748 Symfony est un framework [MVC] [1] écrit en PHP5. Il tire le meilleur parti de l’architecture [MVC] [1] tout en conservant une grande simplicité d’utilisation. Au regard de sa souplesse et de ses grandes possibilités de configuration, Symfony est adapté à tout type de projet web. 
     727Symfony est un framework [MVC] [1] écrit en PHP 5. Il tire le meilleur parti de l’architecture [MVC] [1] tout en conservant une grande simplicité d’utilisation. Au regard de sa souplesse et de ses grandes possibilités de configuration, Symfony est adapté à tout type de projet web. 
    749728 
    750729Maintenant que vous avez compris la théorie sous-jacente à Symfony, vous êtes presque prêt pour développer votre première application. Mais avant cela vous avez besoin d’installer et configurer Symfony sur un serveur de développement.