Development

Documentation/fr_FR/askeet/trunk/D5 (diff)

You must first sign up to be able to contribute.

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

Show
Ignore:
Author:
Jean.Michel.CHAN.CHONG (IP: 80.69.217.68)
Timestamp:
07/31/07 17:58:18 (10 years ago)
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/fr_FR/askeet/trunk/D5

    v3 v4  
    1515{{{ 
    1616#!WikiMarkdown 
    17 Calendrier de l?avent cinquième jour: formulaire et pagineur 
     17Calendrier de l'avent cinquième jour: formulaire et pagineur 
    1818============================================================ 
    1919 
    2121------------------------- 
    2222 
    23 Durant ce long [quatrième jour] (4.txt), nous avons refactoriser notre application en déplaçant des bouts de codes dans des fichiers plus relatifs à leur nature. Vous avez également apprit à modifier le modèle de sorte que des fonctions liées aux données, puissent être mises hors du code de l?action. 
    24  
    25 Le développement est propre, mais le nombre de fonctionnalités est un peu pauvre. Il est temps de permettre un peu plus d?interactivité entre le site askeet et ses utilisateurs. Et les origines de l?interactivité du HTML ? après les liens hypertextes ? sont les formulaires.  
    26  
    27 Les objectifs d?aujourd?hui sont de permettre à l?utilisateur de s?identifier et de mettre en forme la liste des questions de la page d?accueil. Cela sera rapide à développer, mais vous permettra de récupérer d?hier. 
    28  
    29 Formulaire login 
     23Durant ce long [quatrième jour] (4.txt), nous avons refactorisé notre application en déplaçant des bouts de codes dans des fichiers plus relatifs à leur nature. Vous avez également appris à modifier le modèle de sorte que des fonctions liées aux données, puissent être mises hors du code de l'action. 
     24 
     25Le développement est propre, mais le nombre de fonctionnalités est un peu pauvre. Il est temps de permettre un peu plus d'interactivité entre le site askeet et ses utilisateurs. Et les origines de l'interactivité du HTML, autre que les liens hypertextes, ce sont les formulaires.  
     26 
     27Les objectifs d'aujourd'hui sont de permettre à l'utilisateur de s'identifier et de mettre en page la liste des questions de la page d'accueil. Cela sera rapide à développer, mais vous permettra de récupérer d'hier. 
     28 
     29Formulaire Login 
    3030---------------- 
    31 Des utilisateurs sont présents dans les données de test, mais l?application ne peut pas les identifier. Donnons accès à un formulaire de login depuis n?importe quelle page de l?application. Ouvrez le layout global `askeet/apps/frontend/templates/layout.php` et ajoutez la ligne suivante avant le lien `about` :  
     31Des utilisateurs sont présents dans les données de test, mais l'application ne peut pas les identifier. Donnons accès à un formulaire de connexion depuis n'importe quelle page de l'application. Ouvrez le layout global `askeet/apps/frontend/templates/layout.php` et ajoutez la ligne suivante avant le lien `about` :  
    3232 
    3333    [php] 
    3434    <li><?php echo link_to('sign in', 'user/login') ?></li> 
    3535 
    36 >**Note**: le layout courant place ce lien juste derrière la barre d?outils de débogage. Pour la voir, cachez la barre d?outils en cliquant sur l?icône ?Sf?. 
     36>**Note**: le layout courant place ce lien juste derrière la barre d'outils de déboguage. Pour la voir, cachez la barre d?'utils en cliquant sur l'icône ?Sf?. 
    3737 
    3838Il est temps de créer le module `user`. Tandis que le module `question` a été généré lors du deuxième jour, cette fois nous allons juste demander à Symfony de créer le squelette du module, et nous allons écrire le code nous même. 
    4040    $ symfony init-module frontend user 
    4141     
    42 >**Note**: le squelette contient une action `index` par défaut et un template `indexSuccess.php`. Débarrassons-nous en, puisque nous n?en aurons pas besoin. 
    43  
    44 ### Créer l?action user/login 
    45  
    46 Dans le fichier `user/actions/action.class.php` (du nouveau répertoire `askeet/apps/frontend/modules/`), ajoutez l?action `login` :  
     42>**Note**: le squelette contient une action `index` par défaut et un template `indexSuccess.php`. Débarrassons-nous en, puisque nous n'en aurons pas besoin. 
     43 
     44### Créer l'action user/login 
     45 
     46Dans le fichier `user/actions/action.class.php` (du nouveau répertoire `askeet/apps/frontend/modules/`), ajoutez l'action `login` :  
    4747 
    4848    [php] 
    5454    } 
    5555 
    56 L?action sauvegarde la page appelante dans un attribut de requête. Il sera ensuite possible au template de le mettre dans un champ caché, de sorte que l'action cible du formulaire puisse rediriger vers la page appelant, après une authentification réussie. 
    57  
    58 Le `return sfView::SUCCESS` passe le résultat de l?action au template `loginSuccess.php`. Cette instruction est implicite dans les actions qui ne contiennent pas d?instruction de retour, c?est pourquoi le template par défaut d?une action est appelé `actionnameSuccess.php`. 
    59  
    60 Avant de poursuivre cette l?action, jetons un ?il au template. 
     56L'action sauvegarde la page appelante dans un attribut de requête. Il sera ensuite possible au template de le mettre dans un champ caché, de sorte que l'action cible du formulaire puisse rediriger vers la page appelante, après une authentification réussie. 
     57 
     58Le `return sfView::SUCCESS` passe le résultat de l'action au template `loginSuccess.php`. Cette instruction est implicite dans les actions qui ne contiennent pas d'instruction de retour, c'est pourquoi le template par défaut d'une action est appelé `actionnameSuccess.php`. 
     59 
     60Avant de poursuivre cette l'action, jetons un oeil au template. 
    6161 
    6262### Créer le template `loginSuccess.php` 
    6363 
    64 Sur internet beaucoup d?interactions homme-machine utilisent les formulaires, et Symfony facilite la création et le management de ces derniers en fournissant un ensemble **d?assistants**. 
     64Sur internet beaucoup d'interactions homme-machine utilisent les formulaires, et Symfony facilite la création et la gestion de ces derniers en fournissant un ensemble **d'assistants**. 
    6565Dans le répertoire `askeet/apps/frontend/modules/user/templates/`, créez le template `loginSuccess.php`: 
    6666 
    8787    </form> 
    8888 
    89 Ce template est votre première introduction aux assistants de formulaires. Ces fonctions Symfony aident à automatiser l?écriture des formulaires. L?assistant `form_tag()` ouvre un formulaire avec le comportement POST par défaut, et pointe vers l?action passée en argument. L?assistant `input_tag()` produit une balise `<input>` (c?est une suprise) en ajoutant automatiquement l?attribut `id` dont la valeur est égale au premier argument ; la valeur par défaut est donnée par le second argument. Vous pouvez en apprendre plus sur les assistants et sur le code HTML qu?ils génèrent dans le [chapitre relatif] (http://www.symfony-project.com/content/book/page/templating_form_helpers.html) du livre Symfony. 
    90  
    91 La chose essentielle ici est que l?action appelée quand le formulaire est envoyé (l?argument de `form_tag()`) est la même action `login` que pour l?afficher. Ainsi revenons à l?action.  
    92  
    93 ### Traiter l?envoie du formulaire login 
    94  
    95 Remplacez l?action `login` que nous venons d?écrire par le code suivant :  
     89Ce template est votre première introduction aux assistants de formulaires. Ces fonctions Symfony aident à automatiser l'écriture des formulaires. L'assistant `form_tag()` ouvre un formulaire avec le comportement POST par défaut, et pointe vers l'action passée en argument. L'assistant `input_tag()` produit une balise `<input>` (c'est une suprise) en ajoutant automatiquement l'attribut `id` dont la valeur est égale au premier argument ; la valeur par défaut est donnée par le second argument. Vous pouvez en apprendre plus sur les assistants et sur le code HTML qu'ils génèrent dans le [chapitre relatif] (http://www.symfony-project.com/content/book/page/templating_form_helpers.html) du livre Symfony. 
     90 
     91La chose essentielle ici est que l'action appelée quand le formulaire est envoyé (l'argument de `form_tag()`) est la même action `login` que pour l'afficher. Ainsi revenons à l'action.  
     92 
     93### Traiter l'envoi du formulaire Login 
     94 
     95Remplacez l'action `login` que nous venons d'écrire par le code suivant :  
    9696 
    9797    [php] 
    131131    } 
    132132 
    133 L?action login sera utilisée pour afficher le formulaire login et pour le traiter. Par conséquent, elle doit savoir dans quel contexte elle est appelée. Si l?action n?est pas appelée en mode POST, c?est parce qu?elle est appelée depuis un lien : c'est ce dont nous avons parlé précédemment. Si la demande est en mode POST, l?action est appelée par un formulaire et il est temps de le traiter. 
     133L'action login sera utilisée pour afficher le formulaire login et pour le traiter. Par conséquent, elle doit savoir dans quel contexte elle est appelée. Si l'action n'est pas appelée en mode POST, c'est parce qu'elle est appelée depuis un lien : c'est ce dont nous avons parlé précédemment. Si la demande est en mode POST, l'action est appelée par un formulaire et il est temps de le traiter. 
    134134 
    135135L?action prend la valeur du champ `nickname` des paramètres de la requête, et requiert la table `User` pour voir si cet utilisateur existe. 
    136136 
    137 Il y aura, dans un avenir proche, un contrôle du mot de passe qui accordera des droits d?accès à l'utilisateur. Pour le moment, la seule chose que cette action fasse est de stoker dans un attribut de session `l?id`et le `nickname` de l?utilisateur. Eventuellement, l?action redirige à la page appelante grâce au champ caché `referer` du formulaire, passé comme un paramètre de requête. Si le champ est vide, la valeur par défaut (`@homepage`, qui est le nom de la règle de routage pour `question/list`) est utilisée à la place. 
    138  
    139 Notez la différence entre les deux types d?attribut dans cet exemple : les **request attributes** (`$this->getRequest()->setAttribute()`) sont gardés pour le template et perdus dès que la réponse est envoyée à la page appelante. Les **session attributes** (`$this->getUser()->setAttribute()`) sont gardés le temps de la durée de vie de la session utilisateur, et d?autres actions pourront encore y accéder dans le future. Si vous voulez en savoir plus sur les attributs, vous pouvez jeter un ?il au [chapitre de support des paramètres] (http://www.symfony-project.com/content/book/page/parameter_holder.html) du livre Symfony. 
     137Il y aura, dans un avenir proche, un contrôle du mot de passe qui accordera des droits d'accès à l'utilisateur. Pour le moment, la seule chose que cette action fait est de stocker dans un attribut de session `l'id`et le `nickname` de l'utilisateur. Eventuellement, l'action redirige à la page appelante grâce au champ caché `referer` du formulaire, passé comme un paramètre de requête. Si le champ est vide, la valeur par défaut (`@homepage`, qui est le nom de la règle de routage pour `question/list`) est utilisée à la place. 
     138 
     139Notez la différence entre les deux types d'attribut dans cet exemple : les **request attributes** (`$this->getRequest()->setAttribute()`) sont gardés pour le template et perdus dès que la réponse est envoyée à la page appelante. Les **session attributes** (`$this->getUser()->setAttribute()`) sont gardés le temps de la durée de vie de la session utilisateur, et d'autres actions pourront encore y accéder dans le futur. Si vous voulez en savoir plus sur les attributs, vous pouvez jeter un oeil au [chapitre de support des paramètres] (http://www.symfony-project.com/content/book/page/parameter_holder.html) du livre Symfony. 
    140140 
    141141### Accorder des privilèges 
    142142 
    143 C?est une bonne chose que les utilisateurs puissent s?identifier sur le site web askeet, mais ils ne le feront pas juste pour s?amuser. S?identifier sera exiger pour poster une nouvelle question, se déclarer intéressé par une question, et pour évaluer un commentaire. Toutes les autres actions seront accessibles aux utilisateurs non identifiés. 
    144 Pour mettre un utilisateur comme authentifié, vous avez besoin d?appeler la fonction `->setAuthenticated()` de l?objet `sfUser`. Cet objet fournit aussi un mécanisme de droits d?accès (`->addCredential()`), pour affiner la restriction d?accès selon les profiles. Le [chapitre sur les droits d?accès utilisateur](http://www.symfony-project.com/content/book/page/security.html) du livre Symfony explique tout ca en détails. 
    145  
    146  
    147 That's the purpose of the two lines: 
     143C?est une bonne chose que les utilisateurs puissent s'identifier sur le site web askeet, mais ils ne le feront pas juste pour s'amuser. S'identifier sera exigé pour poster une nouvelle question, se déclarer intéressé par une question, et pour évaluer un commentaire. Toutes les autres actions seront accessibles aux utilisateurs non identifiés. 
     144Pour mettre un utilisateur comme authentifié, vous avez besoin d'appeler la fonction `->setAuthenticated()` de l'objet `sfUser`. Cet objet fournit aussi un mécanisme de droits d'accès (`->addCredential()`), pour affiner la restriction d'accès selon les profiles. Le [chapitre sur les droits d'accès utilisateur](http://www.symfony-project.com/content/book/page/security.html) du livre Symfony explique tout ça en détails. 
     145 
     146C'est le but de ces deux lignes : 
    148147 
    149148    [php] 
    151150    $this->getContext()->getUser()->addCredential('subscriber'); 
    152151 
    153 Quand le nom d?utilisateur est identifié, non seulement les données utilisateurs seront mises en variables de session, mais l?accès aux parties réservées sera attribué à l?utilisateur. Nous verrons demain comment restreindre l?accès à certaines parties de l?application aux utilisateurs authentifiés. 
    154  
    155  
    156 ### Ajouter l?action user/logout 
    157  
    158 Il y a une dernière astuce à propos de la fonction `->setAttribute()`: le dernier argument (`subscriber` dans l?exemple précédent) défini l?espace de noms ou l?attribut sera stocké. Non seulement un espace de noms autorise un nom déjà existant dans un autre espace de noms, mais il autorise également la suppression rapide de tous les attributs avec la simple commande : 
     152Quand le nom d'utilisateur est identifié, non seulement les données utilisateurs seront mises en variables de session, mais l'accès aux parties réservées sera attribué à l'utilisateur. Nous verrons demain comment restreindre l'accès à certaines parties de l'application aux utilisateurs authentifiés. 
     153 
     154 
     155### Ajouter l'action user/logout 
     156 
     157Il y a une dernière astuce à propos de la fonction `->setAttribute()`: le dernier argument (`subscriber` dans l'exemple précédent) définit l'espace de noms où l'attribut sera stocké. Non seulement un espace de noms autorise un nom déjà existant dans un autre espace de noms, mais il autorise également la suppression rapide de tous les attributs avec la simple commande : 
    159158 
    160159    [php] 
    169168    } 
    170169 
    171 Employer des espaces de noms nous a évité d'enlever les attributs un à un : c?est une ligne de code en moins. Parlez de paresse ! 
     170Employer des espaces de noms nous a évité d'enlever les attributs un à un : c'est une ligne de code en moins. Parlez de paresse ! 
    172171 
    173172### Mettre à jour le layout 
    174173 
    175 Le layout montre toujours un lien 'login' même si un utilisateur est déjà loggé. Corrigeons vite cela. Dans `askeet/apps/frontend/templates/layout.php`, changez la ligne que nous venons d?ajouter au début du tutorial d?aujourd?hui par :  
     174Le layout montre toujours un lien 'login' même si un utilisateur est déjà connecté. Corrigeons vite cela. Dans `askeet/apps/frontend/templates/layout.php`, changez la ligne que nous venons d'ajouter au début du tutoriel d'aujourd'hui par :  
    176175 
    177176    [php] 
    183182    <?php endif ?> 
    184183 
    185 Il est temps de tester tout ca en affichant quelques pages de l?application. Cliquez sur le lien ?login?, entrez un pseudo valide (?anonymous? devrai faire l?affaire) et valider le. Si le lien ?login? en haut de la fenêtre change en ?sign out?, vous avez tout fait correctement. Eventuellement, essayez de vous déconnecter pour vérifier si le lien ?login? apparait de nouveau. 
     184Il est temps de tester tout ca en affichant n'importe quel page de l'application, cliquez sur le lien 'login', entrez un pseudo valide ('anonymous' devrai faire l'affaire) et validez le. Si le lien 'login' en haut de la fenêtre change en 'sign out', vous avez tout fait correctement. Eventuellement, essayez de vous déconnecter pour vérifier si le lien 'login' apparait de nouveau. 
    186185 
    187186![logged](/images/askeet/logged_day5.gif) 
    188187 
    189 Vous trouverez plus d?informations à propos de la manipulation des attributs de sessions utilisateurs dans le [chapitre sur les sessions utilisateurs](http://www.symfony-project.com/content/book/page/user_session.html) du livre Symfony. 
     188Vous trouverez plus d'informations à propos de la manipulation des attributs de sessions utilisateurs dans le [chapitre sur les sessions utilisateurs](http://www.symfony-project.com/content/book/page/user_session.html) du livre Symfony. 
    190189 
    191190Pagineur de question 
    192191-------------------- 
    193192 
    194 Car des milliers de fans de Symfony se précipiteront sur le site web d'askeet, il est très probable que la liste de questions affichées sur la page d?accueil, va beaucoup s?allonger. Pour éviter les requêtes lentes et le scrolling excessif, il est nécessaire de mettre en page la liste des questions. 
    195 Symfony fournit un objet dans ce but: le `sfPropelPager`. Il encapsule la requête à la base de données de sorte que seuls les enregistrements à afficher sur la page courante soient exigés. Par exemple, si un pagineur est initialisé pour afficher 10 enregistrements par page, la requête à la base de données sera limitée à 10 résultats, et l?offset est mit pour marquer la page. 
     193Car des milliers de fans de Symfony se précipiteront sur le site web d'askeet, il est très probable que la liste de questions affichées sur la page d'accueil, va beaucoup s'allonger. Pour éviter les requêtes lentes et le scrolling excessif, il est nécessaire de mettre en page la liste des questions. 
     194Symfony fournit un objet dans ce but: le `sfPropelPager`. Il encapsule la requête à la base de données de sorte que seuls les enregistrements à afficher sur la page courante soient exigés. Par exemple, si un pagineur est initialisé pour afficher 10 enregistrements par page, la requête à la base de données sera limitée à 10 résultats, et l'offset est mis pour marquer la page. 
    196195 
    197196### Modifier l?action `question/list` 
    198197 
    199 Pendant le [troisième jour] (3.txt),  nous avons vu que l?action `list` du module `question` était tout à fait restreint : 
     198Pendant le [troisième jour] (3.txt),  nous avons vu que l'action `list` du module `question` était tout à fait restreint : 
    200199 
    201200    [php] 
    205204    } 
    206205 
    207 Nous allons modifier cette action, pour passer au template un objet `sfPropelPager` au lieu d?un tableau. Dans le même temps, nous allons classer les questions par nombre d?intéressé : 
     206Nous allons modifier cette action, pour passer au template un objet `sfPropelPager` au lieu d'un tableau. Dans le même temps, nous allons classer les questions par nombre d'intéressé : 
    208207 
    209208    [php] 
    221220    } 
    222221 
    223 L?initialisation de l?objet `sfPropelPager` permet d?indiquer quelle classe il contiendra, et le nombre maximum d?objet qu?il est possible de mettre dans une page (deux dans cet exemple). La fonction `->setPage()` utilise un paramètre pour afficher la page courante. Par exemple, si ce paramètre `page` a la valeur `2`, le `sfPropelPager` retournera les résultats 3 à 5. La valeur par défaut du paramètre de requête `page` étant `1`, ce pagineur retournera les résultats 1 à 2 par défaut. Vous pouvez trouver plus d?informations à propos de l?objet `sfPropelPager` et ses fonctions dans le [chapitre sur la mise en page](http://www.symfony-project.com/content/book/page/pager.html) du livre Symfony. 
     222L'initialisation de l'objet `sfPropelPager` permet d'indiquer quelle classe il contiendra, et le nombre maximum d'objet qu'il est possible de mettre dans une page (deux dans cet exemple). La fonction `->setPage()` utilise un paramètre pour afficher la page courante. Par exemple, si ce paramètre `page` a la valeur `2`, le `sfPropelPager` retournera les résultats 3 à 5. La valeur par défaut du paramètre de requête `page` étant `1`, ce pagineur retournera les résultats 1 à 2 par défaut. Vous pouvez trouver plus d'informations à propos de l'objet `sfPropelPager` et ses fonctions dans le [chapitre sur la mise en page](http://www.symfony-project.com/content/book/page/pager.html) du livre Symfony. 
    224223 
    225224### Utiliser un paramètre personnalisé 
    237236        homepage_max: 2 
    238237 
    239 Ici, la clé `pager` est utilisée comme un espace de nom, c?est pourquoi il apparait également dans le nom du paramètre. Vous pouvez trouver plus d?informations à propos des configurations personnalisées et les règles pour appeler des paramètres faits sur commande dans le [chapitre de configuration](http://www.symfony-project.com/content/book/page/configuration.html) du livre Symfony.   
     238Ici, la clé `pager` est utilisée comme un espace de nom, c'est pourquoi il apparait également dans le nom du paramètre. Vous pouvez trouver plus d'informations à propos des configurations personnalisées et les règles pour appeler des paramètres faits sur commande dans le [chapitre de configuration](http://www.symfony-project.com/content/book/page/configuration.html) du livre Symfony.   
    240239 
    241240### Modifier le template `listSuccess.php` 
    255254### Ajouter une page de navigation 
    256255 
    257 Il y a une chose de plus à ajouter à ce template : la page de navigation. Pour le moment, tout ce que fait le template est d?afficher les deux premières questions, mais nous devrions ajouter la possibilité d?aller aux pages suivantes, et ensuite de revenir aux pages précédentes. Pour faire cela, ajoutez à la fin du template : 
     256Il y a une chose de plus à ajouter à ce template : la page de navigation. Pour le moment, tout ce que fait le template est d'afficher les deux premières questions, mais nous devrions ajouter la possibilité d'aller aux pages suivantes, et ensuite de revenir aux pages précédentes. Pour faire cela, ajoutez à la fin du template : 
    258257 
    259258    [php] 
    273272    </div> 
    274273 
    275 Ce code tire l?avantage des différentes fonctions de l?objet `sfPropelPager`, parmi lesquelles `->haveToPaginate()`, qui retourne `true` seulement si le nombre de résultats de la requête excède la taille de la page ; `->getPreviousPage()`, `->getNextPage()` et `->getLastPage()`, qui ont des significations évidentes ; `->getLinks()`, fournit un tableau des numéros des pages; et `->getCurrentMaxLink()`, qui renvoie le dernier numéro de page. 
    276  
    277 Cette exemple montre également un assistant maniable de liens : link_to_unless()` fera un simple `link_to()` si le test donné comme premier argument est `false`, autrement le texte sera produit sans lien, encapsulé dans un simple `<span>`. 
    278  
    279 Avez-vous testez le pagineur ? Vous devriez. La modification n?est pas effective tant que vous ne l?avez pas validée avec vos propres yeux. Pour cela, ouvrez juste le fichier de données de test créé lors du troisième jour, et ajoutez quelques questions pour que la navigation de page apparaisse. Relancez le batch d?importation des données et rafraichissez la page d?accueil. Voila. 
     274Ce code tire l'avantage des différentes fonctions de l'objet `sfPropelPager`, parmi lesquelles `->haveToPaginate()`, qui retourne `true` seulement si le nombre de résultats de la requête excède la taille de la page ; `->getPreviousPage()`, `->getNextPage()` et `->getLastPage()`, qui ont des significations évidentes ; `->getLinks()`, fournit un tableau des numéros des pages; et `->getCurrentMaxLink()`, qui renvoie le dernier numéro de page. 
     275 
     276Cette exemple montre également un assistant de liens facile à utiliser : link_to_unless()` fera un simple `link_to()` si le test donné comme premier argument est `false`, autrement le texte sera produit sans lien, encapsulé dans un simple `<span>`. 
     277 
     278Avez-vous testé le pagineur ? Vous devriez. La modification n'est pas effective tant que vous ne l'avez pas validée avec vos propres yeux. Pour cela, ouvrez juste le fichier de données de test créé lors du troisième jour, et ajoutez quelques questions pour que la navigation de page apparaisse. Relancez le batch d'importation des données et rafraichissez la page d'accueil. Voila. 
    280279 
    281280![paginated list](/images/askeet/pager_day5.gif) 
    297296      param: { module: question, action: list }  
    298297       
    299 Tant que l?on y est, ajoutez une autre règle de routage pour la page de login : 
     298Tant que l'on y est, ajoutez une autre règle de routage pour la page de login : 
    300299 
    301300    login:  
    308307### Modèle 
    309308 
    310 L?action question/list` exécute du code qui est étroitement lié au modèle, c?est pourquoi nous allons le déplacer dans le modèle. Remplacez le code de l?action `question/list` par : 
     309L?action question/list` exécute du code qui est étroitement lié au modèle, c'est pourquoi nous allons le déplacer dans le modèle. Remplacez le code de l'action `question/list` par : 
    311310 
    312311    [php] 
    332331    } 
    333332 
    334 La même idée appliquée à l?action `question/show`, écrite hier : l?utilisation des objets Propel pour rechercher une question par son titre dépouillé devrait appartenir au modèle. Donc changez l?action `question/show` par: 
     333La même idée appliquée à l'action `question/show`, écrite hier : l'utilisation des objets Propel pour rechercher une question par son titre dépouillé devrait appartenir au modèle. Donc changez l'action `question/show` par: 
    335334 
    336335    [php] 
    362361    <?php echo include_partial('list', array('question_pager' => $question_pager)) ?>  
    363362     
    364 Le contenu du fragment `_list.php` peut être vu dans [l?espace de stockage SVN d?akeet](http://svn.askeet.com/tags/release_day_5/). 
     363Le contenu du fragment `_list.php` peut être vu dans [l'espace de stockage SVN d'askeet](http://svn.askeet.com/tags/release_day_5/). 
    365364 
    366365A demain 
    367366-------- 
    368367 
    369 Les formulaires de login et les pagineurs de liste sont utilisés dans la plupart des applications web de nos jours. Vous avez vu aujourd?hui qu?il était facile de développer avec Symfony. 
    370 Une nouvelle fois, le tutorial finit par un peu de refactorisation. C?est le prix à payer quand vous développez une application petit à petit, sans la concevoir en entier avant. 
    371 Demain, nous continuerons de travailler sur le processus d?authentification, en  limitant l?accès à quelques parties du site aux utilisateurs enregistrés, et nous ferons quelques validations de formulaire pour éviter les soumissions incorrectes.  
     368Les formulaires de login et les pagineurs de liste sont utilisés dans la plupart des applications web de nos jours. Vous avez vu aujourd?hui qu'il était facile de développer avec Symfony. 
     369Une nouvelle fois, le tutorial finit par un peu de refactorisation. C'est le prix à payer quand vous développez une application petit à petit, sans la concevoir en entier avant. 
     370Demain, nous continuerons de travailler sur le processus d'authentification, en limitant l'accès à quelques parties du site aux utilisateurs enregistrés, et nous ferons quelques validations de formulaire pour éviter les soumissions incorrectes.  
    372371 
    373372