Development

Documentation/fr_FR/askeet/3 (diff)

You must first sign up to be able to contribute.

Changes between Version 3 and Version 4 of Documentation/fr_FR/askeet/3

Show
Ignore:
Author:
forresst (IP: 82.251.136.138)
Timestamp:
06/22/08 15:03:25 (9 years ago)
Comment:

Oops : saut de ligne intempestif ????

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/fr_FR/askeet/3

    v3 v4  
    1818 
    1919Calendrier de l’avent troisième jour : plongez dans l’architecture MVC 
    20  
    21 ==================================================================== 
    22  
    23  
     20================================================================= 
    2421 
    2522Précédemment dans Symfony 
    26  
     23--------------------- 
     24 
     25Au cours du [deuxième jour] (2.txt) vous avez appris à construire  un modèle objet basé sur un modèle de données relationnel, et générer une ébauche pour un de ces objets. A ce propos, l’application générée durant les jours précédents est disponible dans l’espace de stockage SVN d’askeet:  
     26 
     27        http://svn.askeet.com/ 
     28 
     29Les objectifs du troisième jour sont de définir une mise en page plus esthétique, définir la liste des questions comme page d’accueil par défaut, afficher le nombre d’utilisateurs intéressés par une question, et de remplir la base de données en utilisant des extraits de fichiers textes afin de disposer de données de test. Ce n’est pas grand chose à faire, mais un peu plus à lire et à comprendre.  
     30 
     31Pour lire ce tutoriel, vous devriez être familiarisé avec les concepts de projet, d’application, module et d’action dans Symfony comme expliqué dans le [chapitre sur le contrôleur](http://www.symfony-project.com/book/1_0/06-Inside-the-Controller-Layer) du livre Symfony. 
     32 
     33Le modèle MVC 
     34------------- 
     35 
     36Aujourd’hui sera le premier plongeon dans le monde de [l’architecture MVC] [1]. Qu’est ce que c’est ? Simplement que le code utilisé pour générer une page est situé dans différents fichiers en fonction de leur nature. 
     37 
     38Si le code concerne la manipulation des données indépendante d’une page, il devrait être situé dans le **Modèle** (la plupart du temps dans `askeet/lib/model/`). S’il concerne la présentation finale, il devrait être situé dans la **Vue** ; dans Symfony, la couche Vue se base sur les templates (par exemple dans `askeet/apps/frontend/modules/question/templates/`) et les fichiers de configuration. Finalement, le code qui sert à lier tout cela et à traduire la logique du site en bon vieux PHP est situé dans le Contrôleur,  et dans Symfony le contrôleur pour une page spécifique est appelé une action (recherchez les actions dans `askeet/apps/frontend/modules/question/actions/`). Vous pouvez en lire plus à propos de ce modèle dans le chapitre sur [l’implémentation de MVC dans Symfony](http://www.symfony-project.com/1_0/02-Exploring-Symfony-s-Code) du livre Symfony. 
     39  
     40Alors que la vue de notre application changera peu aujourd’hui, nous allons manipuler beaucoup de fichiers différents. Cependant ne paniquez pas, puisque l’organisation des fichiers et la séparation du code en différentes couches va bientôt devenir évidente et très utile. 
     41 
     42Changer la mise en page 
    2743------------------------- 
    2844 
    29  
    30  
    31 Au cours du [deuxième jour] (2.txt) vous avez appris à construire  un modèle objet basé sur un modèle de données relationnel, et générer une ébauche pour un de ces objets. A ce propos, l’application générée durant les jours précédents est disponible dans l’espace de stockage SVN d’askeet:  
    32  
    33  
    34  
    35         http://svn.askeet.com/ 
    36  
    37  
    38  
    39 Les objectifs du troisième jour sont de définir une mise en page plus esthétique, définir la liste des questions comme page d’accueil par défaut, afficher le nombre d’utilisateurs intéressés par une question, et de remplir la base de données en utilisant des extraits de fichiers textes afin de disposer de données de test. Ce n’est pas grand chose à faire, mais un peu plus à lire et à comprendre.  
    40  
    41  
    42  
    43 Pour lire ce tutoriel, vous devriez être familiarisé avec les concepts de projet, d’application, module et d’action dans Symfony comme expliqué dans le [chapitre sur le contrôleur](http://www.symfony-project.com/book/1_0/06-Inside-the-Controller-Layer) du livre Symfony. 
    44  
    45  
    46  
    47 Le modèle MVC 
    48  
    49 -------------- 
    50  
    51  
    52  
    53 Aujourd’hui sera le premier plongeon dans le monde de [l’architecture MVC] [1]. Qu’est ce que c’est ? Simplement que le code utilisé pour générer une page est situé dans différents fichiers en fonction de leur nature. 
    54  
    55  
    56  
    57 Si le code concerne la manipulation des données indépendante d’une page, il devrait être situé dans le **Modèle** (la plupart du temps dans `askeet/lib/model/`). S’il concerne la présentation finale, il devrait être situé dans la **Vue** ; dans Symfony, la couche Vue se base sur les templates (par exemple dans `askeet/apps/frontend/modules/question/templates/`) et les fichiers de configuration. Finalement, le code qui sert à lier tout cela et à traduire la logique du site en bon vieux PHP est situé dans le Contrôleur,  et dans Symfony le contrôleur pour une page spécifique est appelé une action (recherchez les actions dans `askeet/apps/frontend/modules/question/actions/`). Vous pouvez en lire plus à propos de ce modèle dans le chapitre sur [l’implémentation de MVC dans Symfony](http://www.symfony-project.com/1_0/02-Exploring-Symfony-s-Code) du livre Symfony. 
    58  
    59   
    60  
    61 Alors que la vue de notre application changera peu aujourd’hui, nous allons manipuler beaucoup de fichiers différents. Cependant ne paniquez pas, puisque l’organisation des fichiers et la séparation du code en différentes couches va bientôt devenir évidente et très utile. 
    62  
    63  
    64  
    65 Changer la mise en page 
    66  
    67 ------------------------- 
    68  
    69  
    70  
    7145Dans l’application du [décorateur][2], le contenu du template appelé par une action est intégré dans un template global, également nommé gabarit principal. En d’autres termes, le gabarit principal contient toutes les parties invariantes de l’interface, il « décore » le résultat de l’action. Ouvrez le gabarit principal (situé dans  `askeet/apps/frontend/templates/layout.php`) et changez-le comme suit :  
    7246 
    73  
    74  
    75     [php] 
    76  
     47    [php] 
    7748    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
    78  
    7949    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
    80  
    8150    <head> 
    82  
    83      
    84  
     51     
    8552    <?php echo include_http_metas() ?> 
    86  
    8753    <?php echo include_metas() ?> 
    88  
    89      
    90  
     54     
    9155    <?php echo include_title() ?> 
    92  
    93      
    94  
     56     
    9557    <link rel="shortcut icon" href="/favicon.ico" /> 
    96  
    97      
    98  
     58     
    9959    </head> 
    100  
    10160    <body> 
    102  
    103      
    104  
     61     
    10562      <div id="header"> 
    106  
    10763        <ul> 
    108  
    10964          <li><?php echo link_to('about', '@homepage') ?></li> 
    110  
    11165        </ul> 
    112  
    11366        <h1><?php echo link_to(image_tag('askeet_logo.gif', 'alt=askeet'), '@homepage') ?></h1> 
    114  
    11567      </div> 
    116  
    117      
    118  
     68     
    11969      <div id="content"> 
    120  
    12170        <div id="content_main"> 
    122  
    12371          <?php echo $sf_data->getRaw('sf_content') ?> 
    124  
    12572          <div class="verticalalign"></div> 
    126  
    12773        </div> 
    128  
    129      
    130  
     74     
    13175        <div id="content_bar"> 
    132  
    13376          <!-- Nothing for the moment --> 
    134  
    13577          <div class="verticalalign"></div> 
    136  
    13778        </div> 
    138  
    13979      </div> 
    140  
    141      
    142  
     80     
    14381    </body> 
    144  
    14582    </html> 
    14683 
    147  
    148  
    14984>**Note**: nous avons essayé de garder les balises aussi sémantique que possible, et de déplacer tout le style dans les feuilles de styles CSS. Ces feuilles de styles ne seront pas décrites ici, puisque la syntaxe CSS n’est pas le but de ce tutoriel. Cependant elles sont disponibles en téléchargement, dans [l’espace de stockage SVN](http://svn.askeet.com/tags/release_day_3/web/css/). 
    150  
    15185> 
    152  
    15386>Nous avons créé deux feuilles de styles (`main.css` et `layout.css`). Copiez les dans le répertoire `askeet/web/css/` et éditez votre `frontend/config/view.yml` pour changer l’auto chargement des feuilles de styles : 
    154  
    15587> 
    156  
    15788>     stylesheets:    [main, layout] 
    158  
    15989> 
    16090 
    161  
    162  
    16391Cette mise en page, un peu légère pour le moment, sera refaite plus tard (dans une semaine environ). Les choses importantes dans ce template sont la partie `<head>`, qui est la plupart du temps générée, et la variable `sf_content`, qui contient le résultat des actions. 
    16492 
    165  
    166  
    16793Vérifiez que les modifications s’affichent correctement en demandant la page d’accueil – cette fois dans l’environnement de développement : 
    16894 
    169  
    170  
    17195    http://askeet/frontend_dev.php/ 
    172  
    173      
    174  
     96     
    17597![updated layout](/images/askeet/congratulations_new.gif) 
    176  
    177      
    178  
     98     
    17999Quelques mots sur les environnements 
    180  
    181100------------------------------ 
    182101 
    183  
    184  
    185102Si vous vous demandez quelle est la différence entre `http://askeet/frontend_dev.php/` et `http://askeet/`, vous devriez jeter un œil sur [le chapitre sur la configuration](http://www.symfony-project.com/book/1_0/05-Configuring-Symfony) du livre Symfony. Pour le moment, vous devez juste savoir qu’elles pointent sur la même application, mais dans des environnements différents. Un environnement est une configuration unique, où quelques fonctionnalités du framework peuvent êtres activées ou désactivées selon le besoin.  
    186103 
    187  
    188  
    189104Dans ce cas, l’url `/frontend_dev.php/` pointe sur **l’environnement de développement**, où toute la configuration est analysée à chaque requête, le cache HTML est désactivé, et les outils de débogage sont tous disponibles (y compris une barre d’outils semi-transparente située dans le coin supérieur de la fenêtre). L’URL `/` - équivalent à `/index.php/` - pointe sur **l’environnement de production**, où la configuration est « compilée » et les outils de débogage sont désactivés pour accélérer la vitesse d’accès aux pages. 
    190105 
    191  
    192  
    193106Ces deux scripts PHP - `frontend_dev.php` et `index.php` – sont appelés **controleurs frontals**, et toutes les requêtes de l’application sont manipulées par eux. Vous pouvez les trouver dans le répertoire `askeet/web/`. En fait, le fichier `index.php` devrait s’appeler `frontend_prod.php`, mais comme le `frontend` est la première application que vous créez, Symfony déduit que vous voudriez probablement que ce soit votre application par défaut et le renomme en `index.php`, c’est donc pour cela que vous pouvez voir votre application en environnement de production juste en demandant `/`. Si vous voulez en apprendre plus à propos du front controller et de la couche contrôleur du modèle MVC en général, référez vous au [chapitre sur le contrôleur] (http://www.symfony-project.com/1_0/06-Inside-the-Controller-Layer) dans le livre Symfony. 
    194107 
    195  
    196  
    197108Un bon principe de base est de naviguer dans l’environnement de développement jusqu'à ce que vous soyez satisfait des fonctionnalités sur lesquelles vous travaillez et de passer à l’environnement de production pour vérifier la vitesse et la beauté des urls. 
    198109 
    199  
    200  
    201110>**Note**: Ne pas oublier de toujours effacer le cache quand vous ajoutez des classes ou quand vous changez des fichiers de configurations pour voir le résultat en environnement de production. 
    202111 
    203  
    204  
    205112Redéfinir la page d’accueil 
    206  
    207113----------------------------- 
    208114 
    209  
    210  
    211115Pour le moment, si vous demandez la page d’accueil du nouveau site, il affiche une page de ‘félicitations’. Une meilleur idée serait d’afficher la liste des questions (référencée dans ces documents comme `question/list` et traduit comme : l’action `list` du module `question`). Pour faire cela, ouvrez le fichier de configuration de routage de l’application frontend, situé dans `askeet/apps/frontend/config/routing.yml` et trouvez la section `homepage:`. Changez-la-en : 
    212116 
    213  
    214  
    215117    homepage: 
    216  
    217118      url:   / 
    218  
    219119      param: { module: question, action: list } 
    220120 
    221  
    222  
    223121Rafraichissez la page d’accueil de l’environnement de développement (`http://askeet/frontend_dev.php/`); elle affiche maintenant la liste des questions. 
    224122 
    225  
    226  
    227123>**Note**: si vous êtes une personne curieuse, vous avez peut être cherché la page contenant le message de ‘félicitations’. Et vous avez surement été surpris de ne pas la trouver dans votre répertoire `askeet`. En fait, le template pour l’action `defaut/index` est situé dans le répertoire data de Symfony et est indépendant du projet. Si vous ne voulez pas en tenir compte, vous pouvez toujours créer un module `défault` dans votre propre projet. 
    228124 
    229  
    230  
    231125Les possibilités offertes par le système de routage seront détaillées prochainement, mais si cela vous intéresse, vous pouvez lire le [chapitre sur le routage](http://www.symfony-project.com/book/1_0/09-Links-and-the-Routing-System) du livre Symfony. 
    232126 
    233  
    234  
    235127Définir des données de test 
    236  
    237128---------------- 
    238129 
    239  
    240  
    241130La liste affichée par la page d’accueil restera vide, à moins que vous ajoutiez vos propres questions. Quand vous développez une application, c’est une bonne idée d’avoir quelques données de test à votre disposition. Entrer des données de test à la main (ou via l’interface CRUD) peut être rébarbatif, c’est pourquoi Symfony peut utiliser les fichiers textes pour remplir les bases de données. 
    242131 
    243  
    244  
    245132Nous allons créer un fichier de données de test dans le répertoire `askeet/data/fixtures/` (ce répertoire doit être créé). Créez un fichier nommé `test_data.yml` avec le contenu suivant : 
    246133 
    247  
    248  
    249134    User: 
    250  
    251135      anonymous: 
    252  
    253136        nickname:   anonymous 
    254  
    255137        first_name: Anonymous 
    256  
    257138        last_name:  Coward 
    258139 
    259  
    260  
    261140      fabien: 
    262  
    263141        nickname:   fabpot 
    264  
    265142        first_name: Fabien 
    266  
    267143        last_name:  Potencier 
    268  
    269      
    270  
     144     
    271145      francois: 
    272  
    273146        nickname:   francoisz 
    274  
    275147        first_name: François 
    276  
    277148        last_name:  Zaninotto 
    278  
    279      
    280  
     149     
    281150    Question: 
    282  
    283151      q1: 
    284  
    285152        title: What shall I do tonight with my girlfriend? 
    286  
    287153        user_id: fabien 
    288  
    289154        body:  | 
    290  
    291155          We shall meet in front of the Dunkin'Donuts before dinner,  
    292  
    293156          and I haven't the slightest idea of what I can do with her.  
    294  
    295157          She's not interested in programming, space opera movies nor insects. 
    296  
    297158          She's kinda cute, so I really need to find something  
    298  
    299159          that will keep her to my side for another evening. 
    300  
    301      
    302  
     160     
    303161      q2: 
    304  
    305162        title: What can I offer to my step mother? 
    306  
    307163        user_id: anonymous 
    308  
    309164        body:  | 
    310  
    311165          My stepmother has everything a stepmother is usually offered 
    312  
    313166          (watch, vacuum cleaner, earrings, del.icio.us account).  
    314  
    315167          Her birthday comes next week, I am broke, and I know that  
    316  
    317168          if I don't offer her something sweet, my girlfriend  
    318  
    319169          won't look at me in the eyes for another month. 
    320  
    321      
    322  
     170     
    323171      q3: 
    324  
    325172        title: How can I generate traffic to my blog? 
    326  
    327173        user_id: francois 
    328  
    329174        body:  | 
    330  
    331175          I have a very swell blog that talks  
    332  
    333176          about my class and mates and pets and favorite movies. 
    334  
    335177           
    336  
    337178    Interest: 
    338  
    339179      i1: { user_id: fabien, question_id: q1 } 
    340  
    341180      i2: { user_id: francois, question_id: q1 } 
    342  
    343181      i3: { user_id: francois, question_id: q2 } 
    344  
    345182      i4: { user_id: fabien, question_id: q2 } 
    346183 
    347  
    348  
    349184Avant tout, vous pouvez reconnaitre ici [YAML] [3]. Si vous n’êtes pas familiarisé avec Symfony, vous pourriez ne pas savoir que le format YAML est le format favori des fichiers de configurations de ce framework. Il n’est pas exclusif – si vous êtes attachés aux fichiers XML ou .ini, il est très facile d’ajouter un gestionnaire de configuration pour permettre à Symfony de les lire. Si vous avez le temps et la patience, vous pouvez en lire plus à propos de YAML et des fichiers de configuration dans le [chapitre de la configuration en pratique](http://www.symfony-project.com/book/1_0/19-Mastering-Symfony-s-Configuration-Files) du livre Symfony. A partir de maintenant, si vous n’êtes pas familiarisé avec la syntaxe YAML, vous devriez [commencer tout de suite] [3], puisque ce tutoriel l’emploiera intensivement. 
    350185 
    351  
    352  
    353186Ok, revenons au fichier de données de test. Il définit des instances d’objets, intitulés avec un nom interne. L’intitulé est d’une bonne utilité pour relier les objets relatifs sans avoir à définir les `id` (qui sont souvent auto incrémentés et qui ne peuvent pas être initialisés). Par exemple, le premier objet créé d’une classe `User`, est intitulé `fabien`. La première `Question` est intitulée `q1`. Ceci rend facile de créer un objet de la classe `Interest` en mentionnant les intitulés des objets relatifs :  
    354187 
    355  
    356  
    357188    Interest: 
    358  
    359189      i1: 
    360  
    361190        user_id: fabien 
    362  
    363191        question_id: q1 
    364192 
    365  
    366  
    367193Le fichier de données donné précédemment utilise la syntaxe courte de YAML pour dire la même chose. Vous pouvez en savoir plus à propos des fichiers de population de données dans le [chapitre sur les fichiers de données](http://www.symfony-project.com/book/1_0/08-Inside-the-Model-Layer) dans le livre Symfony. 
    368194 
    369  
    370  
    371195>**Note**: il n’est pas nécessaire de définir les valeurs pour les colonnes `created_at` et `updated_at` puisque symfony sait comment les remplir par défaut. 
    372196 
    373  
    374  
    375197Créer un batch pour peupler la base de données 
    376  
    377198--------------------------------------- 
    378199 
    379  
    380  
    381200La prochaine étape est de peupler réellement la base de données, et nous désirons le faire avec un script PHP qui peut être appelé en ligne de commande – un batch.  
    382201 
    383  
    384  
    385202### Squelette du batch 
    386203 
    387  
    388  
    389204Créez un fichier appelé `load_data.php` dans le répertoire `askeet/batch/` avec le contenu suivant : 
    390205 
    391  
    392  
    393     [php] 
    394  
     206    [php] 
    395207    <?php 
    396  
    397      
    398  
     208     
    399209    define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..')); 
    400  
    401210    define('SF_APP',         'frontend'); 
    402  
    403211    define('SF_ENVIRONMENT', 'dev'); 
    404  
    405212    define('SF_DEBUG',       true); 
    406  
    407      
    408  
     213     
    409214    require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php'); 
    410  
    411      
    412  
     215     
    413216    // initialize database manager 
    414  
    415217    $databaseManager = new sfDatabaseManager(); 
    416  
    417218    $databaseManager->initialize(); 
    418  
    419      
    420  
     219     
    421220    ?> 
    422221 
    423  
    424  
    425222Le script ne fait rien, ou presque : il définit un chemin, une application et un environnement pour aboutir à une configuration, la charge, et initialise le gestionnaire de base de données. Mais c’est déjà beaucoup : cela signifie que tout le code écrit ci-dessous profitera de l’auto-chargement des classes, la connexion automatique aux objets Propel, et des classes racines de symfony. 
    426223 
    427  
    428  
    429224>**Note**: si vous avez regardé les controlleurs frontaux de symfony (comme `askeet/web/index.php`), vous pourriez trouver ce code extrêmement familier. C’est parce que chaque requête web nécessite l’accès aux mêmes objets et configuration, que le batch. 
    430225 
    431  
    432  
    433226### Importation des données 
    434227 
    435  
    436  
    437228Maintenant que la structure du batch est prête, il est temps d’en faire quelque chose. Le batch doit: 
    438229 
    439  
    440  
    4412301. lire le fichier YAML 
    442  
    4432312. Créer des instances d’objets Propel 
    444  
    4452322. Créer les enregistrements relatifs dans les tables de la base de données concernée 
    446233 
    447  
    448  
    449234Ceci pourrait sembler compliqué, mais avec symfony, vous pouvez le faire avec deux lignes de code, grâce à l’objet `sfPropelData`. Ajoutez juste le code suivant avant le dernier `?>` dans le script `askeet/batch/load_data.php`: 
    450235 
    451  
    452  
    453     [php] 
    454  
     236    [php] 
    455237    $data = new sfPropelData(); 
    456  
    457238    $data->loadData(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'fixtures'); 
    458239 
    459  
    460  
    461240C’est tout. Un objet `sfPropelData` est créé, et dit de charger toutes les données d’un dossier spécifique - notre répertoire `fixtures` – dans la base de données définie dans le fichier de configuration `database.yml`.  
    462241 
    463  
    464  
    465242>**Note**: La constante `DIRECTORY_SEPARATOR` est ici utilisée pour être compatible avec les plateformes Windows et *nix. 
    466243 
    467  
    468  
    469244### Exécuter le batch 
    470245 
    471  
    472  
    473246Enfin, vous pouvez vérifier si ces quelques lignes de code en valaient la peine. Tapez dans la console: 
    474247 
    475  
    476  
    477248    $ cd /home/sfprojects/askeet/batch 
    478  
    479249    $ php load_data.php 
    480  
    481      
    482  
     250     
    483251Vérifiez les modifications en rechargeant la page d'accueil de développement : 
    484252 
    485  
    486  
    487253    http://askeet/frontend_dev.php 
    488  
    489      
    490  
     254     
    491255![loaded data](/images/askeet/fixtures.gif) 
    492256 
    493  
    494  
    495257Hourra, les données sont là. 
    496258 
    497  
    498  
    499259>**Note**: Par défaut, l’objet `sfPropelData` supprime toutes les données avant de charger les nouvelles. Vous pouvez les ajouter aux données actuelles : 
    500  
    501260> 
    502  
    503261>     [php] 
    504  
    505262>     $data = new sfPropelData(); 
    506  
    507263>     $data->setDeleteCurrentData(false); 
    508  
    509264>     $data->loadData(sfConfig::get('sf_data_dir').DIRECTORY_SEPARATOR.'fixtures'); 
    510265 
    511  
    512  
    513266Accès aux données dans le modèle 
    514  
    515267------------------------------- 
    516268 
    517  
    518  
    519269La page affichée en demandant l’action `list` du module `question` est le résultat de la fonction `executeList()` (située dans le fichier action `askeet/apps/frontend/modules/question/actions/action.class.php`) passée au template `askeet/apps/frontend/modules/question/templates/listSuccess.php`. Ceci est basé sur la convention de nommage qui est expliquée dans le [chapitre sur le controller](http://www.symfony-project.com/book/1_0/06-Inside-the-Controller-Layer) dans le livre Symfony. Jetons un œil au code qui est exécuté: 
    520  
    521      
    522  
     270     
    523271actions.class.php: 
    524272 
    525  
    526  
    527     [php] 
    528  
     273    [php] 
    529274    public function executeList () 
    530  
    531275    { 
    532  
    533276      $this->questions = QuestionPeer::doSelect(new Criteria()); 
    534  
    535277    } 
    536278 
    537  
    538  
    539279listSuccess.php: 
    540280 
    541  
    542  
    543     [php] 
    544  
     281    [php] 
    545282    ... 
    546  
    547283    <?php foreach ($questions as $question): ?> 
    548  
    549284    <tr> 
    550  
    551285        <td><?php echo link_to($question->getId(), 'question/show?id='.$question->getId()) ?></td> 
    552  
    553286        <td><?php echo $question->getTitle() ?></td> 
    554  
    555287        <td><?php echo $question->getBody() ?></td> 
    556  
    557288        <td><?php echo $question->getCreatedAt() ?></td> 
    558  
    559289        <td><?php echo $question->getUpdatedAt() ?></td> 
    560  
    561290      </tr> 
    562  
    563291    <?php endforeach; ?> 
    564292 
    565  
    566  
    567293Etape par étape, voici ce qui est fait : 
    568294 
    569  
    570  
    5712951. L’action demande les enregistrements  de la table `Question` qui satisfont un critère vide - par exemple toutes les questions 
    572  
    5732962. Cette liste d’enregistrements est mise dans un tableau (`$questions`) qui est transmis au template 
    574  
    5752973. Le template passe en revue toutes les questions transmis par l’action 
    576  
    5772984. Le template affiche la valeur des colonnes de chaque enregistrement 
    578299 
    579  
    580  
    581300Les fonctions `->getId()`, `->getTitle()`, `->getBody()`, etc. ont été créés lors de l’appel à la commande `symfony propel-build-model` (vous vous rappelez [d’hier](2.txt) ?) pour rechercher la valeur des champs `id`, `title`, `body`, etc. Ce sont les accesseurs standards, formé en ajoutant le préfix `get` et le nom du champ en camelCase – et Propel fournit aussi des mutateurs standards, préfixés de set. La [documentation de Propel][4] décrit les accesseurs créés pour chaque classe.  
    582301 
    583  
    584  
    585302Quant à l’appel mystérieux `QuestionPeer::doSelect(new Criteria())`, c’est aussi une requête standard Propel. La documentation Propel l’expliquera complètement. 
    586303 
    587  
    588  
    589304Ne vous inquiétez pas si vous ne comprenez pas tout le code écrit ci-dessus, il deviendra clair dans quelques jours. 
    590305 
    591  
    592  
    593306Modifier le template question/list 
    594  
    595307--------------------------------- 
    596308 
    597  
    598  
    599309Maintenant que la base de données contient les intérêts pour des questions, il sera facile de récupérer le nombre d’utilisateurs intéressés par une question. Si vous jetez un œil à la classe `BaseQuestion.php` générée par Propel dans le répertoire `askeet/lib/model/om/`, vous noterez la fonction `->getInterests()`. Propel a vu la clé étrangère `question_id` dans la définition de la table `Interest`, et déduit qu'une question a plusieurs intéressés. De ce fait, il est très facile d’afficher ce que nous voulons en modifiant le template `listSuccess.php`, situé dans `askeet/apps/frontend/modules/question/templates/`. Par la suite, nous remplacerons les horribles tables par des jolis divs: 
    600310 
    601  
    602  
    603     [php] 
    604  
     311    [php] 
    605312    <?php use_helper('Text') ?> 
    606  
    607      
    608  
     313     
    609314    <h1>popular questions</h1>  
    610  
    611      
    612  
     315     
    613316    <?php foreach($questions as $question): ?> 
    614  
    615317      <div class="question"> 
    616  
    617318        <div class="interested_block"> 
    618  
    619319          <div class="interested_mark" id="mark_<?php echo $question->getId() ?>"> 
    620  
    621320            <?php echo count($question->getInterests()) ?> 
    622  
    623321          </div> 
    624  
    625322        </div> 
    626  
    627323       
    628  
    629324        <h2><?php echo link_to($question->getTitle(), 'question/show?id='.$question->getId()) ?></h2> 
    630  
    631325       
    632  
    633326        <div class="question_body"> 
    634  
    635327          <?php echo truncate_text($question->getBody(), 200) ?> 
    636  
    637328        </div> 
    638  
    639329      </div> 
    640  
    641330    <?php endforeach; ?> 
    642331 
    643  
    644  
    645332Ici vous reconnaissez la même boucle `foreach` que dans le fichier original `listSuccess.php`. Les fonctions `link_to()` et `truncate_text()` sont des **assistants aux templates** fournis par symfony. La première créée un lien hypertexte d’une autre action du même module, et la seconde tronque le corps de la question à 200 caractères. L’assistant `link_to()` est chargé automatiquement, mais vous devez déclarer l’utilisation du groupe d'assistants `Text` pour utiliser `truncate_text()`.  
    646333 
    647  
    648  
    649334Allez, essayez notre nouveau template en rafraichissant la page d’accueil de développement. 
    650335 
    651  
    652  
    653336    http://askeet/frontend_dev.php/ 
    654  
    655      
    656  
     337     
    657338![liste des meilleures questions](/images/askeet/question_list_day3.gif) 
    658339 
    659  
    660  
    661340Le nombre d’utilisateurs intéressés apparait correctement à coté de chaque question. Pour obtenir la présentation de la capture ci dessus, téléchargez la feuille de styles [`main.css`](http://svn.askeet.com/tags/release_day_3/web/css/main.css) et mettez la dans votre répertoire `askeet/web/css/`. 
    662341 
    663  
    664  
    665342Nettoyage 
    666  
    667343--------- 
    668344 
    669  
    670  
    671345La commande `propel-generate-crud` a créé quelques actions et templates qui ne seront pas nécessaires. Il est temps de les supprimer. 
    672346 
    673  
    674  
    675347Les actions à supprimer dans `askeet/apps/frontend/modules/question/actions/actions.class.php`: 
    676348 
    677  
    678  
    679349* `executeIndex` 
    680  
    681350* `executeEdit` 
    682  
    683351* `executeUpdate` 
    684  
    685352* `executeCreate` 
    686  
    687353* `executeDelete` 
    688354 
    689  
    690  
    691355Les templates à supprimer dans `askeet/apps/frontend/modules/question/templates/`: 
    692356 
    693  
    694  
    695357* `editSuccess.php` 
    696358 
    697  
    698  
    699359A demain 
    700  
    701360-------- 
    702361 
    703  
    704  
    705362Aujourd’hui était une première grande étape dans le monde du paradigme Modèle-Vue-Contrôleur : en manipulant des gabarits, des templates, des actions et des objets du modèle objet Propel, vous avez accédé à toutes les couches d’une application structurée par MVC. Ne vous inquiétez pas si vous n’avez pas compris tous les liens entre ces couches : cela deviendra plus clair petit à petit. 
    706363 
    707  
    708  
    709364Beaucoup de fichiers ont été ouverts aujourd’hui, et si vous voulez savoir comment les fichiers sont organisés dans un projet, référez vous au [chapitre sur la structure de fichier](http://www.symfony-project.com/book/1_0/04-The-Basics-of-Page-Creation) du livre symfony. 
    710365 
    711  
    712  
    713366Demain sera un autre grand jour : nous modifierons les vues, installerons une politique de routage plus complexe, modifierons le modèle, et plongerons en profondeur dans la manipulation des données et les liens entre les tables. 
    714367 
    715  
    716  
    717368Jusque-là, dormez bien, et sentez vous libre de consulter la source du tutorial d’aujourd’hui (tag `release_day_3`) à: 
    718369 
    719  
    720  
    721370    http://svn.askeet.com/tags/release_day_3 
    722371 
    723  
    724  
    725372[1]: http://en.wikipedia.org/wiki/Model-view-controller "Model-View-Controller definition at Wikipedia" 
    726  
    727373[2]: http://en.wikipedia.org/wiki/Decorator_pattern     "Decorator pattern definition at Wikipedia" 
    728  
    729374[3]: http://www.yaml.org/                               "YAML" 
    730  
    731375[4]: http://propel.phpdb.org/docs/user_guide/           "Propel documentation" 
    732376 
    733377 
    734  
    735378}}}