/jobeet/fr/14.markdown
Markdown | 412 lines | 343 code | 69 blank | 0 comment | 0 complexity | 35964a4e0b3a7de47fe7c81d81ff968d MD5 | raw file
1Jour 14 : Les Flux 2================== 3 4Hier, vous avez commencé à développer votre première application symfony. Ne vous arrêtez 5pas maintenant. Car vous en apprendrez davantage sur symfony, essayez d'ajouter de nouvelles 6fonctionnalités à votre application, l'héberger quelque part, et la partager avec la communauté. 7 8Passons à quelque chose de complètement différent aujourd'hui. 9 10Si vous êtes à la recherche d'un emploi, vous aurez probablement besoin d'être informé 11dès qu'un nouveau poste est affiché. Parce qu'il n'est pas très pratique de vérifier le 12site web toutes les heures, nous allons ajouter plusieurs flux d'emploi aujourd'hui pour 13que nos utilisateurs Jobeet soient mis au courant. 14 15Les formats 16----------- 17 18Le framework symfony a un support natif pour les ~formats|Formats~ et les 19~mime-types|Mime Types~. Cela signifie que le même modèle et contrôleur peut 20avoir différents ~Templates|Templates~ basés sur le format requêté. Le 21format par défaut est HTML, mais symfony supporte ~plusieurs autres formats|Formats 22intégrés~ comme `txt`, `js`, `css`, `json`, `xml`, `rdf`, ou 23`atom`. 24 25Le format peut être définie en utilisant la méthode `setRequestFormat()` de l'objet de 26la ~requête|Requête HTTP~ : 27 28 [php] 29 $request->setRequestFormat('xml'); 30 31Mais la plupart du temps, le format est incorporé dans l'URL. Dans ce cas, symfony 32va le mettre pour vous, si la variable spéciale ~`sf_format`~ est utilisé dans la route 33correspondante. Pour la liste des emplois, l'URL de la liste est : 34 35 http://www.jobeet.com.localhost/frontend_dev.php/job 36 37Cette URL est équivalent à : 38 39 http://www.jobeet.com.localhost/frontend_dev.php/job.html 40 41Les deux URL sont équivalentes car les routes générés par la classe 42`sfPropelRouteCollection` ont le `sf_format` comme extension et parce 43que le HTML est le format par défaut. Vous pouvez le vérifier vous-même en 44exécutant la tâche `app:routes` : 45 46 47 48Les flux 49-------- 50 51### Le flux du dernier emploi 52 53Le support de différents formats est aussi facile que la création de Templates différents. 54Pour créer un [flux Atom](http://en.wikipedia.org/wiki/Atom_(standard)) pour les derniers 55emplois, créez un Template `indexSuccess.atom.php` : 56 57 [php] 58 <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php --> 59 <?xml version="1.0" encoding="utf-8"?> 60 <feed xmlns="http://www.w3.org/2005/Atom"> 61 <title>Jobeet</title> 62 <subtitle>Latest Jobs</subtitle> 63 <link href="" rel="self"/> 64 <link href=""/> 65 <updated></updated> 66 <author><name>Jobeet</name></author> 67 <id>Unique Id</id> 68 69 <entry> 70 <title>Job title</title> 71 <link href="" /> 72 <id>Unique id</id> 73 <updated></updated> 74 <summary>Job description</summary> 75 <author><name>Company</name></author> 76 </entry> 77 </feed> 78 79>**SIDEBAR** 80>Les noms des Templates 81> 82>Comme `html` est le format le plus couramment utilisé pour les applications web, il peut être 83>omis du nom du Template. Les deux Templates `indexSuccess.php` et `indexSuccess.html.php` 84>sont équivalents et symfony utilise le premier qu'il trouve. 85> 86>Pourquoi les Templates par défaut sont suffixés avec `Success` ? Une action ne peut 87>retourner une valeur pour indiquer le Template à rendre. Si l'action renvoie rien, il 88>est équivalent au code suivant : 89> 90> [php] 91> return sfView::SUCCESS; // == 'Success' 92> 93>Si vous voulez changer le suffixe, retournez simplement autre chose : 94> 95> [php] 96> return sfView::ERROR; // == 'Error' 97> 98> return 'Foo'; 99> 100>Comme nous l'avons vu dans la journée précédente, le nom du Template peut 101>également être modifié en utilisant la méthode `setTemplate()` : 102> 103> [php] 104> $this->setTemplate('foo'); 105 106Par défaut, symfony va changer le ~`Content-Type`~ de la réponse en fonction du 107format, et pour tous les formats non-HTML, le layout est désactivé. Pour un flux Atom, 108symfony change le `Content-Type` en `application/atom+xml; 109charset=utf-8`. 110 111Dans le pied de page de Jobeet, mettez à jour le lien vers le flux : 112 113 [php] 114 <!-- apps/frontend/templates/layout.php --> 115 <li class="feed"> 116 <a href="<?php echo url_for('job', array('sf_format' => 'atom')) ?>">Full feed</a> 117 </li> 118 119L'~URI interne|URI interne~ est la même que pour la liste `job` avec le 120`sf_format` ajouté comme une variable. 121 122Ajoutez un balise `<link>` dans la section d'entête du layout pour permettre 123de découvrir par le navigateur automatiquement notre flux : 124 125 [php] 126 <!-- apps/frontend/templates/layout.php --> 127 <link rel="alternate" type="application/atom+xml" title="Latest Jobs" 128 href="<?php echo url_for('job', array('sf_format' => 'atom'), true) ?>" /> 129 130Pour l'attribut `href` du lien, une ~URL (Absolue)~ est utilisée grâce au second 131argument du helper `url_for()`. 132 133Remplacer l'entête du Template Atom avec le code suivant : 134 135 [php] 136 <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php --> 137 <title>Jobeet</title> 138 <subtitle>Latest Jobs</subtitle> 139 <link href="<?php echo url_for('job', array('sf_format' => 'atom'), true) ?>" rel="self"/> 140 <link href="<?php echo url_for('homepage', true) ?>"/> 141<propel> 142 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', JobeetJobPeer::getLatestPost()->getCreatedAt('U')) ?></updated> 143</propel> 144<doctrine> 145 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', Doctrine_Core::getTable('JobeetJob')->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated> 146</doctrine> 147 <author> 148 <name>Jobeet</name> 149 </author> 150 <id><?php echo sha1(url_for('job', array('sf_format' => 'atom'), true)) ?></id> 151 152<propel> 153Notez l'utilisation du `U` comme un argument pour `getCreatedAt()` pour obtenir 154la date comme un timestamp. Pour obtenir la date du dernier post, créez la méthode 155`getLatestPost()` : 156</propel> 157<doctrine> 158Notez l'utilisation du `U` comme un argument pour `format()` pour obtenir la date 159comme un timestamp. Pour obtenir la date du dernier post, créez la méthode 160`getLatestPost()` : 161</doctrine> 162 163<propel> 164 [php] 165 // lib/model/JobeetJobPeer.php 166 class JobeetJobPeer extends BaseJobeetJobPeer 167 { 168 static public function getLatestPost() 169 { 170 $criteria = new Criteria(); 171 self::addActiveJobsCriteria($criteria); 172 173 return JobeetJobPeer::doSelectOne($criteria); 174 } 175 176 // ... 177 } 178</propel> 179<doctrine> 180 [php] 181 // lib/model/doctrine/JobeetJobTable.class.php 182 class JobeetJobTable extends Doctrine_Table 183 { 184 public function getLatestPost() 185 { 186 $q = Doctrine_Query::create() 187 ->from('JobeetJob j'); 188 $this->addActiveJobsQuery($q); 189 190 return $q->fetchOne(); 191 } 192 193 // ... 194 } 195</doctrine> 196 197Les entrées du flux peuvent être générées par le code suivant : 198 199 [php] 200 <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php --> 201 <?php use_helper('Text') ?> 202 <?php foreach ($categories as $category): ?> 203 <?php foreach ($category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')) as $job): ?> 204 <entry> 205 <title> 206 <?php echo $job->getPosition() ?> (<?php echo $job->getLocation() ?>) 207 </title> 208 <link href="<?php echo url_for('job_show_user', $job, true) ?>" /> 209 <id><?php echo sha1($job->getId()) ?></id> 210<propel> 211 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getCreatedAt('U')) ?></updated> 212</propel> 213<doctrine> 214 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getDateTimeObject('created_at')->format('U')) ?></updated> 215</doctrine> 216 <summary type="xhtml"> 217 <div xmlns="http://www.w3.org/1999/xhtml"> 218 <?php if ($job->getLogo()): ?> 219 <div> 220 <a href="<?php echo $job->getUrl() ?>"> 221 <img src="http://<?php echo $sf_request->getHost().'/uploads/jobs/'.$job->getLogo() ?>" 222 alt="<?php echo $job->getCompany() ?> logo" /> 223 </a> 224 </div> 225 <?php endif ?> 226 227 <div> 228 <?php echo simple_format_text($job->getDescription()) ?> 229 </div> 230 231 <h4>How to apply?</h4> 232 233 <p><?php echo $job->getHowToApply() ?></p> 234 </div> 235 </summary> 236 <author> 237 <name><?php echo $job->getCompany() ?></name> 238 </author> 239 </entry> 240 <?php endforeach ?> 241 <?php endforeach ?> 242 243La méthode `getHost()` de l'objet de la requête (`$sf_request`) retourne 244l'hôte actuel, qui est très pratique pour créer un lien absolu pour le logo 245de l'entreprise. 246 247 248 249>**TIP** 250>Lors de la création d'un flux, le ~débogage|Deboguer~ est plus facile si vous utilisez 251>des outils en ligne de commande comme [`curl`](http://curl.haxx.se/) ou 252>[`wget`](http://www.gnu.org/software/wget/), car vous voyez le contenu actuel 253>du flux. 254 255### Les derniers emplois dans le flux de la catégorie 256 257L'un des objectifs de Jobeet est d'aider les gens à trouver un emploi plus ciblées. Donc, 258nous devons fournir un flux pour chaque catégorie. 259 260D'abord, nous allons mettre à jour la route `category` pour ajouter le support de différents formats : 261 262 [yml] 263 // apps/frontend/config/routing.yml 264 category: 265 url: /category/:slug.:sf_format 266 class: sfPropelRoute 267 param: { module: category, action: show, sf_format: html } 268 options: { model: JobeetCategory, type: object } 269 requirements: 270 sf_format: (?:html|atom) 271 272Maintenant, la route `category` comprend à la fois les formats `html` et `atom`. 273Mettez à jour les flux de la catégorie dans les ~Templates|Templates~ : 274 275 [php] 276 <!-- apps/frontend/modules/job/templates/indexSuccess.php --> 277 <div class="feed"> 278 <a href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom')) ?>">Feed</a> 279 </div> 280 281 <!-- apps/frontend/modules/category/templates/showSuccess.php --> 282 <div class="feed"> 283 <a href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom')) ?>">Feed</a> 284 </div> 285 286La dernière étape consiste à créer le Template `showSuccess.atom.php`. Mais comme ce 287flux sera également la liste des emplois, nous pouvons ~refactoriser|Refactorisation~ le 288code qui génère les entrées du flux en créant un partial `_list.atom.php`. Comme pour le 289format `html`, les ~partials|Templates Partial~ ont un format spécifique : 290 291 [php] 292 <!-- apps/frontend/modules/job/templates/_list.atom.php --> 293 <?php use_helper('Text') ?> 294 295 <?php foreach ($jobs as $job): ?> 296 <entry> 297 <title><?php echo $job->getPosition() ?> (<?php echo $job->getLocation() ?>)</title> 298 <link href="<?php echo url_for('job_show_user', $job, true) ?>" /> 299 <id><?php echo sha1($job->getId()) ?></id> 300<propel> 301 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getCreatedAt('U')) ?></updated> 302</propel> 303<doctrine> 304 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getDateTimeObject('created_at')->format('U')) ?></updated> 305</doctrine> 306 <summary type="xhtml"> 307 <div xmlns="http://www.w3.org/1999/xhtml"> 308 <?php if ($job->getLogo()): ?> 309 <div> 310 <a href="<?php echo $job->getUrl() ?>"> 311 <img src="http://<?php echo $sf_request->getHost().'/uploads/jobs/'.$job->getLogo() ?>" 312 alt="<?php echo $job->getCompany() ?> logo" /> 313 </a> 314 </div> 315 <?php endif ?> 316 317 <div> 318 <?php echo simple_format_text($job->getDescription()) ?> 319 </div> 320 321 <h4>How to apply?</h4> 322 323 <p><?php echo $job->getHowToApply() ?></p> 324 </div> 325 </summary> 326 <author> 327 <name><?php echo $job->getCompany() ?></name> 328 </author> 329 </entry> 330 <?php endforeach ?> 331 332Vous pouvez utiliser le partial `_list.atom.php` pour simplifier le Template du flux emploi : 333 334 [php] 335 <!-- apps/frontend/modules/job/templates/indexSuccess.atom.php --> 336 <?xml version="1.0" encoding="utf-8"?> 337 <feed xmlns="http://www.w3.org/2005/Atom"> 338 <title>Jobeet</title> 339 <subtitle>Latest Jobs</subtitle> 340 <link href="<?php echo url_for('job', array('sf_format' => 'atom'), true) ?>" rel="self"/> 341 <link href="<?php echo url_for('homepage', true) ?>"/> 342<propel> 343 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', JobeetJobPeer::getLatestPost()->getCreatedAt('U')) ?></updated> 344</propel> 345<doctrine> 346 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', Doctrine_Core::getTable('JobeetJob')->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated> 347</doctrine> 348 <author> 349 <name>Jobeet</name> 350 </author> 351 <id><?php echo sha1(url_for('job', array('sf_format' => 'atom'), true)) ?></id> 352 353 <?php foreach ($categories as $category): ?> 354 <?php include_partial('job/list', array('jobs' => $category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')))) ?> 355 <?php endforeach ?> 356 </feed> 357 358Enfin, créez le Template `showSuccess.atom.php` : 359 360 [php] 361 <!-- apps/frontend/modules/category/templates/showSuccess.atom.php --> 362 <?xml version="1.0" encoding="utf-8"?> 363 <feed xmlns="http://www.w3.org/2005/Atom"> 364 <title>Jobeet (<?php echo $category ?>)</title> 365 <subtitle>Latest Jobs</subtitle> 366 <link href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom'), true) ?>" rel="self" /> 367 <link href="<?php echo url_for('category', array('sf_subject' => $category), true) ?>" /> 368<propel> 369 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $category->getLatestPost()->getCreatedAt('U')) ?></updated> 370</propel> 371<doctrine> 372 <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $category->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated> 373</doctrine> 374 <author> 375 <name>Jobeet</name> 376 </author> 377 <id><?php echo sha1(url_for('category', array('sf_subject' => $category), true)) ?></id> 378 379 <?php include_partial('job/list', array('jobs' => $pager->getResults())) ?> 380 </feed> 381 382Quant au flux principal des emplois, nous avons besoin de la date du dernier emploi pour une catégorie : 383 384 [php] 385<propel> 386 // lib/model/JobeetCategory.php 387</propel> 388<doctrine> 389 // lib/model/doctrine/JobeetCategory.class.php 390</doctrine> 391 class JobeetCategory extends BaseJobeetCategory 392 { 393 public function getLatestPost() 394 { 395 return $this->getActiveJobs(1)->getFirst(); 396 } 397 398 // ... 399 } 400 401 402 403À demain 404-------- 405 406Comme avec de nombreuses fonctionnalités de symfony, le support du format natif vou 407permet d'ajouter des flux à vos sites Web sans effort. 408 409Aujourd'hui, nous avons amélioré l'expérience du demandeur d'emploi. Demain, nous allons 410voir comment assurer une plus grande exposition aux annonceurs en leur fournissant un service Web. 411 412__ORM__