Skip to content
Caution: You are browsing the legacy symfony 1.x part of this website.

Jour 14 : Les Flux

Symfony version
Language
ORM

Hier, vous avez commencĂ© Ă  dĂ©velopper votre premiĂšre application symfony. Ne vous arrĂȘtez pas maintenant. Car vous en apprendrez davantage sur symfony, essayez d'ajouter de nouvelles fonctionnalitĂ©s Ă  votre application, l'hĂ©berger quelque part, et la partager avec la communautĂ©.

Passons à quelque chose de complÚtement différent aujourd'hui.

Si vous ĂȘtes Ă  la recherche d'un emploi, vous aurez probablement besoin d'ĂȘtre informĂ© dĂšs qu'un nouveau poste est affichĂ©. Parce qu'il n'est pas trĂšs pratique de vĂ©rifier le site web toutes les heures, nous allons ajouter plusieurs flux d'emploi aujourd'hui pour que nos utilisateurs Jobeet soient mis au courant.

Les formats

Le framework symfony a un support natif pour les formats et les mime-types. Cela signifie que le mĂȘme modĂšle et contrĂŽleur peut avoir diffĂ©rents Templates basĂ©s sur le format requĂȘtĂ©. Le format par dĂ©faut est HTML, mais symfony supporte plusieurs autres formats comme txt, js, css, json, xml, rdf, ou atom.

Le format peut ĂȘtre dĂ©finie en utilisant la mĂ©thode setRequestFormat() de l'objet de la requĂȘte :

$request->setRequestFormat('xml');

Mais la plupart du temps, le format est incorporé dans l'URL. Dans ce cas, symfony va le mettre pour vous, si la variable spéciale sf_format est utilisé dans la route correspondante. Pour la liste des emplois, l'URL de la liste est :

http://www.jobeet.com.localhost/frontend_dev.php/job

Cette URL est équivalent à :

http://www.jobeet.com.localhost/frontend_dev.php/job.html

Les deux URL sont Ă©quivalentes car les routes gĂ©nĂ©rĂ©s par la classe sfDoctrineRouteCollection ont le sf_format comme extension et parce que le HTML est le format par dĂ©faut. Vous pouvez le vĂ©rifier vous-mĂȘme en exĂ©cutant la tĂąche app:routes :

Cli

Les flux

Le flux du dernier emploi

Le support de différents formats est aussi facile que la création de Templates différents. Pour créer un flux Atom pour les derniers emplois, créez un Template indexSuccess.atom.php :

<!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Jobeet</title>
  <subtitle>Latest Jobs</subtitle>
  <link href="" rel="self"/>
  <link href=""/>
  <updated></updated>
  <author><name>Jobeet</name></author>
  <id>Unique Id</id>
 
  <entry>
    <title>Job title</title>
    <link href="" />
    <id>Unique id</id>
    <updated></updated>
    <summary>Job description</summary>
    <author><name>Company</name></author>
  </entry>
</feed>

sidebar

Les noms des Templates

Comme html est le format le plus couramment utilisĂ© pour les applications web, il peut ĂȘtre omis du nom du Template. Les deux Templates indexSuccess.php et indexSuccess.html.php sont Ă©quivalents et symfony utilise le premier qu'il trouve.

Pourquoi les Templates par défaut sont suffixés avec Success ? Une action ne peut retourner une valeur pour indiquer le Template à rendre. Si l'action renvoie rien, il est équivalent au code suivant :

return sfView::SUCCESS; // == 'Success'

Si vous voulez changer le suffixe, retournez simplement autre chose :

return sfView::ERROR; // == 'Error'
 
return 'Foo';

Comme nous l'avons vu dans la journĂ©e prĂ©cĂ©dente, le nom du Template peut Ă©galement ĂȘtre modifiĂ© en utilisant la mĂ©thode setTemplate() :

$this->setTemplate('foo');

Par défaut, symfony va changer le Content-Type de la réponse en fonction du format, et pour tous les formats non-HTML, le layout est désactivé. Pour un flux Atom, symfony change le Content-Type en application/atom+xml; charset=utf-8.

Dans le pied de page de Jobeet, mettez Ă  jour le lien vers le flux :

<!-- apps/frontend/templates/layout.php -->
<li class="feed">
  <a href="<?php echo url_for('job', array('sf_format' => 'atom')) ?>">Full feed</a>
</li>

L'URI interne est la mĂȘme que pour la liste job avec le sf_format ajoutĂ© comme une variable.

Ajoutez un balise <link> dans la section d'entĂȘte du layout pour permettre de dĂ©couvrir par le navigateur automatiquement notre flux :

<!-- apps/frontend/templates/layout.php -->
<link rel="alternate" type="application/atom+xml" title="Latest Jobs"
  href="<?php echo url_for('job', array('sf_format' => 'atom'), true) ?>" />

Pour l'attribut href du lien, une URL (Absolue) est utilisée grùce au second argument du helper url_for().

Remplacer l'entĂȘte du Template Atom avec le code suivant :

<!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
<title>Jobeet</title>
<subtitle>Latest Jobs</subtitle>
<link href="<?php echo url_for('job', array('sf_format' => 'atom'), true) ?>" rel="self"/>
<link href="<?php echo url_for('homepage', true) ?>"/>
<updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', Doctrine_Core::getTable('JobeetJob')->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated>
<author>
  <name>Jobeet</name>
</author>
<id><?php echo sha1(url_for('job', array('sf_format' => 'atom'), true)) ?></id>

Notez l'utilisation du U comme un argument pour format() pour obtenir la date comme un timestamp. Pour obtenir la date du dernier post, créez la méthode getLatestPost() :

// lib/model/doctrine/JobeetJobTable.class.php
class JobeetJobTable extends Doctrine_Table
{
  public function getLatestPost()
  {
    $q = Doctrine_Query::create()
      ->from('JobeetJob j');
    $this->addActiveJobsQuery($q);
 
    return $q->fetchOne();
  }
 
  // ...
}

Les entrĂ©es du flux peuvent ĂȘtre gĂ©nĂ©rĂ©es par le code suivant :

<!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
<?php use_helper('Text') ?>
<?php foreach ($categories as $category): ?>
  <?php foreach ($category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')) as $job): ?>
    <entry>
      <title>
        <?php echo $job->getPosition() ?> (<?php echo $job->getLocation() ?>)
      </title>
      <link href="<?php echo url_for('job_show_user', $job, true) ?>" />
      <id><?php echo sha1($job->getId()) ?></id>
      <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getDateTimeObject('created_at')->format('U')) ?></updated>
      <summary type="xhtml">
       <div xmlns="http://www.w3.org/1999/xhtml">
         <?php if ($job->getLogo()): ?>
           <div>
             <a href="<?php echo $job->getUrl() ?>">
               <img src="http://<?php echo $sf_request->getHost().'/uploads/jobs/'.$job->getLogo() ?>"
                 alt="<?php echo $job->getCompany() ?> logo" />
             </a>
           </div>
         <?php endif ?>
 
         <div>
           <?php echo simple_format_text($job->getDescription()) ?>
         </div>
 
         <h4>How to apply?</h4>
 
         <p><?php echo $job->getHowToApply() ?></p>
       </div>
      </summary>
      <author>
        <name><?php echo $job->getCompany() ?></name>
      </author>
    </entry>
  <?php endforeach ?>
<?php endforeach ?>

La mĂ©thode getHost() de l'objet de la requĂȘte ($sf_request) retourne l'hĂŽte actuel, qui est trĂšs pratique pour crĂ©er un lien absolu pour le logo de l'entreprise.

Flux

tip

Lors de la création d'un flux, le débogage est plus facile si vous utilisez des outils en ligne de commande comme curl ou wget, car vous voyez le contenu actuel du flux.

Les derniers emplois dans le flux de la catégorie

L'un des objectifs de Jobeet est d'aider les gens à trouver un emploi plus ciblées. Donc, nous devons fournir un flux pour chaque catégorie.

D'abord, nous allons mettre à jour la route category pour ajouter le support de différents formats :

// apps/frontend/config/routing.yml
category:
  url:     /category/:slug.:sf_format
  class:   sfDoctrineRoute
  param:   { module: category, action: show, sf_format: html }
  options: { model: JobeetCategory, type: object }
  requirements:
    sf_format: (?:html|atom)

Maintenant, la route category comprend à la fois les formats html et atom. Mettez à jour les flux de la catégorie dans les Templates :

<!-- apps/frontend/modules/job/templates/indexSuccess.php -->
<div class="feed">
  <a href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom')) ?>">Feed</a>
</div>
 
<!-- apps/frontend/modules/category/templates/showSuccess.php -->
<div class="feed">
  <a href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom')) ?>">Feed</a>
</div>

La derniÚre étape consiste à créer le Template showSuccess.atom.php. Mais comme ce flux sera également la liste des emplois, nous pouvons refactoriser le code qui génÚre les entrées du flux en créant un partial _list.atom.php. Comme pour le format html, les partials ont un format spécifique :

<!-- apps/frontend/modules/job/templates/_list.atom.php -->
<?php use_helper('Text') ?>
 
<?php foreach ($jobs as $job): ?>
  <entry>
    <title><?php echo $job->getPosition() ?> (<?php echo $job->getLocation() ?>)</title>
    <link href="<?php echo url_for('job_show_user', $job, true) ?>" />
    <id><?php echo sha1($job->getId()) ?></id>
      <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $job->getDateTimeObject('created_at')->format('U')) ?></updated>
    <summary type="xhtml">
     <div xmlns="http://www.w3.org/1999/xhtml">
       <?php if ($job->getLogo()): ?>
         <div>
           <a href="<?php echo $job->getUrl() ?>">
             <img src="http://<?php echo $sf_request->getHost().'/uploads/jobs/'.$job->getLogo() ?>"
               alt="<?php echo $job->getCompany() ?> logo" />
           </a>
         </div>
       <?php endif ?>
 
       <div>
         <?php echo simple_format_text($job->getDescription()) ?>
       </div>
 
       <h4>How to apply?</h4>
 
       <p><?php echo $job->getHowToApply() ?></p>
     </div>
    </summary>
    <author>
      <name><?php echo $job->getCompany() ?></name>
    </author>
  </entry>
<?php endforeach ?>

Vous pouvez utiliser le partial _list.atom.php pour simplifier le Template du flux emploi :

<!-- apps/frontend/modules/job/templates/indexSuccess.atom.php -->
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Jobeet</title>
  <subtitle>Latest Jobs</subtitle>
  <link href="<?php echo url_for('job', array('sf_format' => 'atom'), true) ?>" rel="self"/>
  <link href="<?php echo url_for('homepage', true) ?>"/>
  <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', Doctrine_Core::getTable('JobeetJob')->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated>
  <author>
    <name>Jobeet</name>
  </author>
  <id><?php echo sha1(url_for('job', array('sf_format' => 'atom'), true)) ?></id>
 
<?php foreach ($categories as $category): ?>
  <?php include_partial('job/list', array('jobs' => $category->getActiveJobs(sfConfig::get('app_max_jobs_on_homepage')))) ?>
<?php endforeach ?>
</feed>

Enfin, créez le Template showSuccess.atom.php :

<!-- apps/frontend/modules/category/templates/showSuccess.atom.php -->
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Jobeet (<?php echo $category ?>)</title>
  <subtitle>Latest Jobs</subtitle>
  <link href="<?php echo url_for('category', array('sf_subject' => $category, 'sf_format' => 'atom'), true) ?>" rel="self" />
  <link href="<?php echo url_for('category', array('sf_subject' => $category), true) ?>" />
  <updated><?php echo gmstrftime('%Y-%m-%dT%H:%M:%SZ', $category->getLatestPost()->getDateTimeObject('created_at')->format('U')) ?></updated>
  <author>
    <name>Jobeet</name>
  </author>
  <id><?php echo sha1(url_for('category', array('sf_subject' => $category), true)) ?></id>
 
  <?php include_partial('job/list', array('jobs' => $pager->getResults())) ?>
</feed>

Quant au flux principal des emplois, nous avons besoin de la date du dernier emploi pour une catégorie :

// lib/model/doctrine/JobeetCategory.class.php
class JobeetCategory extends BaseJobeetCategory
{
  public function getLatestPost()
  {
    return $this->getActiveJobs(1)->getFirst();
  }
 
  // ...
}

Flux de la catégorie

À demain

Comme avec de nombreuses fonctionnalités de symfony, le support du format natif vou permet d'ajouter des flux à vos sites Web sans effort.

Aujourd'hui, nous avons amélioré l'expérience du demandeur d'emploi. Demain, nous allons voir comment assurer une plus grande exposition aux annonceurs en leur fournissant un service Web.

This work is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License license.