Development

Documentation/fr_FR/askeet: 5.txt

You must first sign up to be able to contribute.

Documentation/fr_FR/askeet: 5.txt

File 5.txt, 20.2 kB (added by nicocsgamer, 11 years ago)
Line 
1 Calendrier de l?avent cinqui� jour: formulaire et pagineur
2 ============================================================
3
4 Pr�demment dans Symfony
5 -------------------------
6
7 Durant ce long [quatri� jour] (4.txt), nous avons refactoriser notre application en d�a�t des bouts de codes dans des fichiers plus relatifs �eur nature. Vous avez �lement apprit �odifier le mod� de sorte que des fonctions li� aux donn�, puissent �e mises hors du code de l?action.
8
9 Le d�loppement est propre, mais le nombre de fonctionnalit�est un peu pauvre. Il est temps de permettre un peu plus d?interactivit�ntre le site askeet et ses utilisateurs. Et les origines de l?interactivit�u HTML ? apr�les liens hypertextes ? sont les formulaires.
10
11 Les objectifs d?aujourd?hui sont de permettre �?utilisateur de s?identifier et de mettre en forme la liste des questions de la page d?accueil. Cela sera rapide ��lopper, mais vous permettra de r�p�r d?hier.
12
13 Formulaire login
14 ----------------
15 Des utilisateurs sont pr�nts dans les donn� de test, mais l?application ne peut pas les identifier. Donnons acc��n 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`�:
16
17     [php]
18     <li><?php echo link_to('sign in', 'user/login') ?></li>
19
20 >**Note**: le layout courant place ce lien juste derri� la barre d?outils de d�gage. Pour la voir, cachez la barre d?outils en cliquant sur l?ic�?Sf?.
21
22 Il est temps de cr� le module `user`. Tandis que le module `question` a � g�r�ors du deuxi� jour, cette fois nous allons juste demander �ymfony de cr� le squelette du module, et nous allons �ire le code nous m�.
23
24     $ symfony init-module frontend user
25    
26 >**Note**: le squelette contient une action `index` par d�ut et un template `indexSuccess.php`. D�rrassons-nous en, puisque nous n?en aurons pas besoin.
27
28 ### Cr� l?action user/login
29
30 Dans le fichier `user/actions/action.class.php` (du nouveau r�rtoire `askeet/apps/frontend/modules/`), ajoutez l?action `login`�:
31
32     [php]
33     public function executeLogin()
34     {
35       $this->getRequest()->setAttribute('referer', $this->getRequest()->getReferer());
36  
37       return sfView::SUCCESS;
38     }
39
40 L?action sauvegarde la page appelante dans un attribut de requ�. 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�une authentification r�sie.
41
42 Le `return sfView::SUCCESS` passe le r�ltat 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�ut d?une action est appel�actionnameSuccess.php`.
43
44 Avant de poursuivre cette l?action, jetons un ?il au template.
45
46 ### Cr� le template `loginSuccess.php`
47
48 Sur internet beaucoup d?interactions homme-machine utilisent les formulaires, et Symfony facilite la cr�ion et le management de ces derniers en fournissant un ensemble **d?assistants**.
49 Dans le r�rtoire `askeet/apps/frontend/modules/user/templates/`, cr� le template `loginSuccess.php`:
50
51     [php]
52     <?php echo form_tag('user/login') ?>
53    
54       <fieldset>
55    
56       <div class="form-row">
57         <label for="nickname">nickname:</label>
58         <?php echo input_tag('nickname', $sf_params->get('nickname')) ?>
59       </div>
60    
61       <div class="form-row">
62         <label for="password">password:</label>
63         <?php echo input_password_tag('password') ?>
64       </div>
65    
66       </fieldset>
67      
68       <?php echo input_hidden_tag('referer', $sf_request->getAttribute('referer')) ?>
69       <?php echo submit_tag('sign in') ?>
70    
71     </form>
72
73 Ce template est votre premi� introduction aux assistants de formulaires. Ces fonctions Symfony aident �utomatiser l?�iture des formulaires. L?assistant `form_tag()` ouvre un formulaire avec le comportement POST par d�ut, et pointe vers l?action pass�en argument. L?assistant `input_tag()` produit une balise `<input>` (c?est une suprise) en ajoutant automatiquement l?attribut `id` dont la valeur est �le au premier argument�; la valeur par d�ut est donn�par le second argument. Vous pouvez en apprendre plus sur les assistants et sur le code HTML qu?ils g�rent dans le [chapitre relatif] (http://www.symfony-project.com/content/book/page/templating_form_helpers.html) du livre Symfony.
74
75 La chose essentielle ici est que l?action appel�quand le formulaire est envoy�l?argument de `form_tag()`) est la m� action `login` que pour l?afficher. Ainsi revenons �?action.
76
77 ### Traiter l?envoie du formulaire login
78
79 Remplacez l?action `login` que nous venons d?�ire par le code suivant�:
80
81     [php]
82     public function executeLogin()
83     {
84       if ($this->getRequest()->getMethod() != sfRequest::POST)
85       {
86         // display the form
87         $this->getRequest()->setAttribute('referer', $this->getRequest()->getReferer());
88       }
89       else
90       {
91         // handle the form submission
92         $nickname = $this->getRequestParameter('nickname');
93  
94         $c = new Criteria();
95         $c->add(UserPeer::NICKNAME, $nickname);
96         $user = UserPeer::doSelectOne($c);
97      
98         // nickname exists?
99         if ($user)
100         {
101           // password is OK?
102           if (true)
103           {
104             $this->getUser()->setAuthenticated(true);
105             $this->getUser()->addCredential('subscriber');
106    
107             $this->getUser()->setAttribute('subscriber_id', $user->getId(), 'subscriber');
108             $this->getUser()->setAttribute('nickname', $user->getNickname(), 'subscriber');
109  
110             // redirect to last page
111             return $this->redirect($this->getRequestParameter('referer', '@homepage'));
112           }
113         }
114       }
115     }
116
117 L?action login sera utilis�pour afficher le formulaire login et pour le traiter. Par cons�ent, elle doit savoir dans quel contexte elle est appel� Si l?action n?est pas appel�en mode POST, c?est parce qu?elle est appel�depuis un lien�: c'est ce dont nous avons parl�r�demment. Si la demande est en mode POST, l?action est appel�par un formulaire et il est temps de le traiter.
118
119 L?action prend la valeur du champ `nickname` des param�es de la requ�, et requiert la table `User` pour voir si cet utilisateur existe.
120
121 Il y aura, dans un avenir proche, un contr�du mot de passe qui accordera des droits d?acc��'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 �a page appelante gr� au champ cach�referer` du formulaire, pass�omme un param�e de requ�. Si le champ est vide, la valeur par d�ut (`@homepage`, qui est le nom de la r�e de routage pour `question/list`) est utilis��a place.
122
123 Notez la diff�nce entre les deux types d?attribut dans cet exemple�: les **request attributes** (`$this->getRequest()->setAttribute()`) sont gard�pour le template et perdus d�que la r�nse est envoy��a page appelante. Les **session attributes** (`$this->getUser()->setAttribute()`) sont gard�le temps de la dur�de vie de la session utilisateur, et d?autres actions pourront encore y acc�r dans le future. Si vous voulez en savoir plus sur les attributs, vous pouvez jeter un ?il au [chapitre de support des param�es] (http://www.symfony-project.com/content/book/page/parameter_holder.html) du livre Symfony.
124
125 ### Accorder des privil�s
126
127 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�arer int�ss�ar une question, et pour �luer un commentaire. Toutes les autres actions seront accessibles aux utilisateurs non identifi�
128 Pour mettre un utilisateur comme authentifi�vous avez besoin d?appeler la fonction `->setAuthenticated()` de l?objet `sfUser`. Cet objet fournit aussi un m�nisme de droits d?acc�(`->addCredential()`), pour affiner la restriction d?acc�selon les profiles. Le [chapitre sur les droits d?acc�utilisateur](http://www.symfony-project.com/content/book/page/security.html) du livre Symfony explique tout ca en d�ils.
129
130
131 That's the purpose of the two lines:
132
133     [php]
134     $this->getContext()->getUser()->setAuthenticated(true);
135     $this->getContext()->getUser()->addCredential('subscriber');
136
137 Quand le nom d?utilisateur est identifi�non seulement les donn� utilisateurs seront mises en variables de session, mais l?acc�aux parties r�rv� sera attribu� l?utilisateur. Nous verrons demain comment restreindre l?acc��ertaines parties de l?application aux utilisateurs authentifi�
138
139
140 ### Ajouter l?action user/logout
141
142 Il y a une derni� astuce �ropos de la fonction `->setAttribute()`: le dernier argument (`subscriber` dans l?exemple pr�dent) d�ni l?espace de noms ou l?attribut sera stock�Non seulement un espace de noms autorise un nom d� existant dans un autre espace de noms, mais il autorise �lement la suppression rapide de tous les attributs avec la simple commande�:
143
144     [php]
145     public function executeLogout()
146     {
147       $this->getUser()->setAuthenticated(false);
148       $this->getUser()->clearCredentials();
149    
150       $this->getUser()->getAttributeHolder()->removeNamespace('subscriber');
151    
152       $this->redirect('@homepage');
153     }
154
155 Employer des espaces de noms nous a �t�'enlever les attributs un �n�: c?est une ligne de code en moins. Parlez de paresse�!
156
157 ### Mettre �our le layout
158
159 Le layout montre toujours un lien 'login' m� si un utilisateur est d� logg�Corrigeons vite cela. Dans `askeet/apps/frontend/templates/layout.php`, changez la ligne que nous venons d?ajouter au d�t du tutorial d?aujourd?hui par�:
160
161     [php]
162     <?php if ($sf_user->isAuthenticated()): ?>
163       <li><?php echo link_to('sign out', 'user/logout') ?></li>
164       <li><?php echo link_to($sf_user->getAttribute('nickname', '', 'subscriber').' profile', 'user/profile') ?></li>
165     <?php else: ?>
166       <li><?php echo link_to('sign in/register', 'user/login') ?></li>
167     <?php endif ?>
168
169 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�e change en ?sign out?, vous avez tout fait correctement. Eventuellement, essayez de vous d�nnecter pour v�fier si le lien ?login? apparait de nouveau.
170
171 ![logged](/images/askeet/logged_day5.gif)
172
173 Vous trouverez plus d?informations �ropos 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.
174
175 Pagineur de question
176 --------------------
177
178 Car des milliers de fans de Symfony se pr�piteront sur le site web d'askeet, il est tr�probable que la liste de questions affich� sur la page d?accueil, va beaucoup s?allonger. Pour �ter les requ�s lentes et le scrolling excessif, il est n�ssaire de mettre en page la liste des questions.
179 Symfony fournit un objet dans ce but: le `sfPropelPager`. Il encapsule la requ� �a base de donn� de sorte que seuls les enregistrements �fficher sur la page courante soient exig� Par exemple, si un pagineur est initialis�our afficher 10 enregistrements par page, la requ� �a base de donn� sera limit��0 r�ltats, et l?offset est mit pour marquer la page.
180
181 ### Modifier l?action `question/list`
182
183 Pendant le [troisi� jour] (3.txt),  nous avons vu que l?action `list` du module `question` �it tout �ait restreint�:
184
185     [php]
186     public function executeList ()
187     {
188       $this->questions = QuestionPeer::doSelect(new Criteria());
189     }
190
191 Nous allons modifier cette action, pour passer au template un objet `sfPropelPager` au lieu d?un tableau. Dans le m� temps, nous allons classer les questions par nombre d?int�ss�
192
193     [php]
194     public function executeList ()
195     {
196       $pager = new sfPropelPager('Question', 2);
197       $c = new Criteria();
198       $c->addDescendingOrderByColumn(QuestionPeer::INTERESTED_USERS);
199       $pager->setCriteria($c);
200       $pager->setPage($this->getRequestParameter('page', 1));
201       $pager->setPeerMethod('doSelectJoinUser');
202       $pager->init();
203  
204       $this->question_pager = $pager;
205     }
206
207 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�e pour afficher la page courante. Par exemple, si ce param�e `page` a la valeur `2`, le `sfPropelPager` retournera les r�ltats 3 �. La valeur par d�ut du param�e de requ� `page` �nt `1`, ce pagineur retournera les r�ltats 1 � par d�ut. Vous pouvez trouver plus d?informations �ropos 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.
208
209 ### Utiliser un param�e personnalis�
210 C'est toujours une bonne id�de mettre les constantes que vous utilisez dans des fichiers de configuration. Par exemple, le nombre de r�ltats par page (`2` dans cet exemple) pourrait �e remplac�ar un param�e, d�ni dans la configuration personnalis�de votre application. Changer la ligne de `new sfPropelPager` ci-dessus par :
211
212     [php]
213     ...
214       $pager = new sfPropelPager('Question', sfConfig::get('app_pager_homepage_max'));
215
216 Ouvrez le fichier de configuration personnalis�`askeet/apps/frontend/config/app.yml`) de votre application et ajoutez-y�:
217
218     all:
219       pager:
220         homepage_max: 2
221
222 Ici, la cl�pager` est utilis�comme un espace de nom, c?est pourquoi il apparait �lement dans le nom du param�e. Vous pouvez trouver plus d?informations �ropos des configurations personnalis� et les r�es pour appeler des param�es faits sur commande dans le [chapitre de configuration](http://www.symfony-project.com/content/book/page/configuration.html) du livre Symfony. 
223
224 ### Modifier le template `listSuccess.php`
225
226 Dans le template `listSuccess.php`, remplacez juste la ligne�:
227
228     [php]
229     <?php foreach($questions as $question): ?>
230
231 par
232
233     [php]
234     <?php foreach($question_pager->getResults() as $question): ?>
235
236 de sorte que la page affiche la liste de r�ltats stock� dans le pagineur.
237
238 ### Ajouter une page de navigation
239
240 Il y a une chose de plus �jouter �e template�: la page de navigation. Pour le moment, tout ce que fait le template est d?afficher les deux premi�s questions, mais nous devrions ajouter la possibilit�?aller aux pages suivantes, et ensuite de revenir aux pages pr�dentes. Pour faire cela, ajoutez �a fin du template�:
241
242     [php]
243     <div id="question_pager">
244     <?php if ($question_pager->haveToPaginate()): ?>
245       <?php echo link_to('&laquo;', 'question/list?page=1') ?>
246       <?php echo link_to('&lt;', 'question/list?page='.$question_pager->getPreviousPage()) ?>
247    
248       <?php foreach ($question_pager->getLinks() as $page): ?>
249         <?php echo link_to_unless($page == $question_pager->getPage(), $page, 'question/list?page='.$page) ?>
250         <?php echo ($page != $question_pager->getCurrentMaxLink()) ? '-' : '' ?>
251       <?php endforeach; ?>
252    
253       <?php echo link_to('&gt;', 'question/list?page='.$question_pager->getNextPage()) ?>
254       <?php echo link_to('&raquo;', 'question/list?page='.$question_pager->getLastPage()) ?>
255     <?php endif; ?>
256     </div>
257
258 Ce code tire l?avantage des diff�ntes fonctions de l?objet `sfPropelPager`, parmi lesquelles `->haveToPaginate()`, qui retourne `true` seulement si le nombre de r�ltats de la requ� exc� la taille de la page�; `->getPreviousPage()`, `->getNextPage()` et `->getLastPage()`, qui ont des significations �dentes�;�`->getLinks()`, fournit un tableau des num�s des pages; et `->getCurrentMaxLink()`, qui renvoie le dernier num� de page.
259
260 Cette exemple montre �lement un assistant maniable de liens�: link_to_unless()` fera un simple `link_to()` si le test donn�omme premier argument est `false`, autrement le texte sera produit sans lien, encapsul�ans un simple `<span>`.
261
262 Avez-vous testez le pagineur�? Vous devriez. La modification n?est pas effective tant que vous ne l?avez pas valid�avec vos propres yeux. Pour cela, ouvrez juste le fichier de donn� de test cr�lors du troisi� jour, et ajoutez quelques questions pour que la navigation de page apparaisse. Relancez le batch d?importation des donn� et rafraichissez la page d?accueil. Voila.
263
264 ![paginated list](/images/askeet/pager_day5.gif)
265
266 ### Ajoutez une r�e de routage pour les pages suivantes
267
268 Par d�ut, les urls des pages ressembleront �
269
270     http://askeet/frontend_dev.php/question/list/page/XX
271    
272 Tirons profit des r�es de routage pour que ces pages soient interpr�es�:
273
274     http://askeet/frontend_dev.php/index/XX
275  
276 Ouvrez juste le fichier `apps/frontend/config/routing.yml` et ajoutez au d�t�:
277  
278     popular_questions:
279       url:   /index/:page
280       param: { module: question, action: list }
281      
282 Tant que l?on y est, ajoutez une autre r�e de routage pour la page de login�:
283
284     login:
285       url:   /login
286       param: { module: user, action: login }
287
288 Refactorisation
289 ---------------
290
291 ### Mod�
292
293 L?action question/list` ex�te du code qui est �oitement li�u mod�, c?est pourquoi nous allons le d�acer dans le mod�. Remplacez le code de l?action `question/list` par�:
294
295     [php]
296     public function executeList ()
297     {
298       $this->question_pager = QuestionPeer::getHomepagePager($this->getRequestParameter('page', 1));
299     }
300
301 ?et ajoutez la fonction suivante dans la classe `QuestionPeer.php` situ�dans `lib/model`�:
302    
303     [php]
304     public static function getHomepagePager($page)
305     {
306       $pager = new sfPropelPager('Question', sfConfig::get('app_pager_homepage_max'));
307       $c = new Criteria();
308       $c->addDescendingOrderByColumn(self::INTERESTED_USERS);
309       $pager->setCriteria($c);
310       $pager->setPage($page);
311       $pager->setPeerMethod('doSelectJoinUser');
312       $pager->init();
313  
314       return $pager;
315     }
316
317 La m� id�appliqu��?action `question/show`, �ite hier�: l?utilisation des objets Propel pour rechercher une question par son titre d�uill�evrait appartenir au mod�. Donc changez l?action `question/show` par:
318
319     [php]
320     public function executeShow()
321     {
322       $this->question = QuestionPeer::getQuestionFromTitle($this->getRequestParameter('stripped_title'));
323  
324       $this->forward404Unless($this->question);
325     }
326
327 Ajoutez �QuestionPeer.php`:
328
329     [php]
330     public static function getQuestionFromTitle($title)
331     {
332       $c = new Criteria();
333       $c->add(QuestionPeer::STRIPPED_TITLE, $title);
334
335       return self::doSelectOne($c);
336     }
337
338 ### Templates
339
340 La liste des questions affich� dans `question/templates/listSuccess.php` sera r�ilis�ailleurs dans le future. Donc nous allons d�acer le code du template pour afficher une liste de question dans le fragment `_list.php` et remplacer le contenu de `listSuccess.php` par un simple�:
341
342     [php]
343     <h1>popular questions</h1>
344    
345     <?php echo include_partial('list', array('question_pager' => $question_pager)) ?>
346    
347 Le contenu du fragment `_list.php` peut �e vu dans [l?espace de stockage SVN d?akeet](http://svn.askeet.com/tags/release_day_5/).
348
349 A demain
350 --------
351
352 Les formulaires de login et les pagineurs de liste sont utilis�dans la plupart des applications web de nos jours. Vous avez vu aujourd?hui qu?il �it facile de d�lopper avec Symfony.
353 Une nouvelle fois, le tutorial finit par un peu de refactorisation. C?est le prix �ayer quand vous d�loppez une application petit �etit, sans la concevoir en entier avant.
354 Demain, nous continuerons de travailler sur le processus d?authentification, en  limitant l?acc��uelques parties du site aux utilisateurs enregistr� et nous ferons quelques validations de formulaire pour �ter les soumissions incorrectes.
355