Symfony2 - Jobeet - Jour 14 - Flux de données

1 1 1 1 1 1 1 1 1 1 Rating 0.00 (0 Votes)
Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google PlusSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn

Si vous êtes à la recherche d'un emploi, vous aurez probablement besoin d'être informé dès qu'un nouveau poste est disponible. Parce qu'il n'est pas très pratique de consulter le site web toutes les deux heures, nous allons ajouter plusieurs flux d'offres pour que nos utilisateurs Jobeet se tiennent à jour.

Les formats de template

Les templates sont un moyen générique pour rendre le contenu dans n'importe quel format. Bien que dans la plupart des cas vous utilisez des templates pour afficher le contenu HTML, un template peut tout aussi bien générer JavaScript, CSS, XML ou tout autre format.

Par exemple, la même "ressource" est souvent affichée dans plusieurs formats. Pour afficher une page au format XML, il suffit d'inclure le format dans le nom du template:

  • Nom du template XML: AcmeArticleBundle:Article:index.xml.twig
  • Nom de fichier du template XML: index.xml.twig

En réalité, ce n'est rien de plus qu'une convention de nommage et le template n'est actuellement pas affiché différemment en fonction de son format.

Dans de nombreux cas, vous voudrez peut-être permettre à un seul contrôleur de rendre plusieurs formats différents en fonction du "format demandé". Pour cette raison, un motif commun est de faire ce qui suit :

public function indexAction()
{
    $format = $this->getRequest()->getRequestFormat();
 
    return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig');
}

La méthode getRequestFormat de l'objet Request est par défaut au format html, mais peut renvoyer n'importe quel autre format basé sur le format demandé par l'utilisateur. Le format de la demande est le plus souvent géré par le routage, où une route peut être configurée de sorte que /contact définit le format html alors que /contact.xml définit le format xml.

Pour créer des liens qui incluent le paramètre de format, incluez une clé _format dans le paramètre :

<a href={{ path('article_show', {'id': 123, '_format': 'pdf'}) }}>
    PDF Version
</a>

RSS

FLUX DES DERNIÈRES OFFRES

Supporter différents formats est aussi facile que créer différents templates. Pour créer un flux Atom des dernières offres, créez un template index.atom.twig :

  • src/Erlem/JobeetBundle/Resources/views/Job/index.atom.twig
<?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>

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

  • src/Erlem/JobeetBundle/Resources/views/layout.html.twig
<!-- ... -->

<li class="feed"><a href={{ path('erlem_job', {'_format': 'atom'}) }}>Full feed</a></li>

<!-- ... -->

Ajoutez une balise <link> dans la section <head> du layout pour permettre la découverte automatique par le navigateur de notre flux :

  • src/Erlem/JobeetBundle/Resources/views/layout.html.twig
<!-- ... -->

<link rel="alternate" type="application/atom+xml" title="Latest Jobs" href={{ url('erlem_job', {'_format': 'atom'}) }} />

<!-- ... -->

Dans JobController, modifiez indexAction pour afficher le modèle en fonction de _format :

  • src/Erlem/JobeetBundle/Controller/JobController.php
// ...

$format = $this->getRequest()->getRequestFormat();

return $this->render('ErlemJobeetBundle:Job:index.'.$format.'.twig', array(
    'categories' => $categories
));

// ...

Remplacez l'en-tête du template Atom avec le code suivant :

  • src/Erlem/JobeetBundle/Resources/views/Job/index.atom.twig
<!-- ... -->

    <title>Jobeet</title>
    <subtitle>Latest Jobs</subtitle>
    <link href={{ url('erlem_job', {'_format': 'atom'}) }} rel="self"/>
    <link href={{ url('erlem_jobeet_homepage') }}/>
    <updated>{{ lastUpdated }}</updated>
    <author><name>Jobeet</name></author>
    <id>{{ feedId }}</id>

<!-- ... -->

Dans JobController, nous devons envoyer les paramètres LastUpdated et feedId au template :

  • src/Erlem/JobeetBundle/Controller/JobController.php
// ...

        $latestJob = $em->getRepository('ErlemJobeetBundle:Job')->getLatestPost();

        if($latestJob) {
            $lastUpdated = $latestJob->getCreatedAt()->format(DATE_ATOM);
        } else {
            $lastUpdated = new \DateTime();
            $lastUpdated = $lastUpdated->format(DATE_ATOM);
        }

        $format = $this->getRequest()->getRequestFormat();
        return $this->render('ErlemJobeetBundle:Job:index.'.$format.'.twig', array(
               'categories' => $categories,
               'lastUpdated' => $lastUpdated,
               'feedId' => sha1($this->get('router')->generate('erlem_job', array('_format'=> 'atom'), true)),
        ));
// ...

Pour obtenir la date du dernier article, nous devons créer la méthode getLatestPost() dans JobRepository :

  • src/Erlem/JobeetBundle/Repository/JobRepository.php
// ...

    public function getLatestPost($category_id = null)
    {
        $query = $this->createQueryBuilder('j')
            ->where('j.expires_at > :date')
            ->setParameter('date', date('Y-m-d H:i:s', time()))
            ->andWhere('j.is_activated = :activated')
            ->setParameter('activated', 1)
            ->orderBy('j.expires_at', 'DESC')
            ->setMaxResults(1);

        if($category_id) {
            $query->andWhere('j.category = :category_id')
                ->setParameter('category_id', $category_id);
        }

        try{
            $job = $query->getQuery()->getSingleResult();
        } catch(\Doctrine\Orm\NoResultException $e){
            $job = null;
        }

        return $job;    
    }
// ...

Les entrées du flux peuvent être générées avec le code suivant :

  • src/Erlem/JobeetBundle/Resources/views/Job/index.atom.twig
{% for category in categories %}
    {% for entity in category.activejobs %}
        <entry>
            <title>{{ entity.position }} ({{ entity.location }})</title>
            <link href={{ url('erlem_job_show', { 'id': entity.id, 'company': entity.companyslug, 'location': entity.locationslug, 'position': entity.positionslug }) }} />
            <id>{{ entity.id }}</id>
            <updated>{{ entity.createdAt.format(constant('DATE_ATOM')) }}</updated>
            <summary type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    {% if entity.logo %}
                        <div>
                            <a href={{ entity.url }}>
                                <img src="http://{{ app.request.host }}/uploads/jobs/{{ entity.logo }} alt={{ entity.company }} logo' />
                            </a>
                        </div>
                    {% endif %}
                    <div>
                        {{ entity.description|nl2br }}
                    </div>
                    <h4>How to apply?</h4>
                    <p>{{ entity.howtoapply }}</p>
                </div>
            </summary>
            <author><name>{{ entity.company }}</name></author>
        </entry>
    {% endfor %}
{% endfor %}

DERNIÈRES OFFRES DANS UN FLUX DE CATÉGORIE

L'un des objectifs de Jobeet est d'aider les gens à trouver des offres plus ciblées. Nous devons donc fournir un flux pour chaque catégorie.

Tout d'abord, nous allons mettre à jour les liens vers les flux de la catégorie dans les templates :

  • src/Erlem/JobeetBundle/Resources/views/Job/index.html.twig
<div class="feed">
    <a href={{ path('ErlemJobeetBundle_category', { 'slug': category.slug, '_format': 'atom' }) }}>Feed</a>
</div>
  • src/Erlem/JobeetBundle/Resources/views/Category/show.html.twig
<div class="feed">
    <a href={{ path('ErlemJobeetBundle_category', { 'slug': category.slug, '_format': 'atom' }) }}>Feed</a>
</div>

Mettez à jour showAction de CategoryController pour afficher le template correspondant :

  • src/Erlem/JobeetBundle/Controller/CategoryController.php
// ...
    public function showAction($slug, $page)
    {
        $em = $this->getDoctrine()->getManager();

        $category = $em->getRepository('ErlemJobeetBundle:Category')->findOneBySlug($slug);

        if (!$category) {
            throw $this->createNotFoundException('Unable to find Category entity.');
        }

        $latestJob = $em->getRepository('ErlemJobeetBundle:Job')->getLatestPost($category->getId());

        if($latestJob) {
            $lastUpdated = $latestJob->getCreatedAt()->format(DATE_ATOM); 
        } else {
            $lastUpdated = new \DateTime();
            $lastUpdated = $lastUpdated->format(DATE_ATOM);
        }

        $total_jobs = $em->getRepository('ErlemJobeetBundle:Job')->countActiveJobs($category->getId());
        $jobs_per_page = $this->container->getParameter('max_jobs_on_category');
        $last_page = ceil($total_jobs / $jobs_per_page);
        $previous_page = $page > 1 ? $page - 1 : 1;
        $next_page = $page < $last_page ? $page + 1 : $last_page; 
        $category->setActiveJobs($em->getRepository('ErlemJobeetBundle:Job')->getActiveJobs($category->getId(), $jobs_per_page, ($page - 1) * $jobs_per_page));

        $format = $this->getRequest()->getRequestFormat();

        return $this->render('ErlemJobeetBundle:Category:show.' . $format . '.twig', array(
            'category' => $category,
            'last_page' => $last_page,
            'previous_page' => $previous_page,
            'current_page' => $page,
            'next_page' => $next_page,
            'total_jobs' => $total_jobs,
            'feedId' => sha1($this->get('router')->generate('ErlemJobeetBundle_category', array('slug' => $category->getSlug(), 'format' => 'atom'), true)),
            'lastUpdated' => $lastUpdated    
        ));
    }

Finalement, créez le template show.atom.twig :

  • src/Erlem/JobeetBundle/Resources/views/Category/show.atom.twig
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Jobeet ({{ category.name }})</title>
    <subtitle>Latest Jobs</subtitle>
    <link href={{ url('ErlemJobeetBundle_category', { 'slug': category.slug, '_format': 'atom' }) }} rel="self" />
    <updated>{{ lastUpdated }}</updated>
    <author><name>Jobeet</name></author>
    <id>{{ feedId }}</id>

    {% for entity in category.activejobs %}
        <entry>
            <title>{{ entity.position }} ({{ entity.location }})</title>
            <link href={{ url('erlem_job_show', { 'id': entity.id, 'company': entity.companyslug, 'location': entity.locationslug, 'position': entity.positionslug }) }} />
            <id>{{ entity.id }}</id>
            <updated>{{ entity.createdAt.format(constant('DATE_ATOM')) }}</updated>
            <summary type="xhtml">
                <div xmlns="http://www.w3.org/1999/xhtml">
                    {% if entity.logo %}
                        <div>
                            <a href={{ entity.url }}>
                                <img src="http://{{ app.request.host }}/uploads/jobs/{{ entity.logo }} alt={{ entity.company }} logo" />
                            </a>
                        </div>
                    {% endif %}
                    <div>
                        {{ entity.description|nl2br }}
                    </div>
                    <h4>How to apply?</h4>
                    <p>{{ entity.howtoapply }}</p>
                </div>
            </summary>
            <author><name>{{ entity.company }}</name></author>
        </entry>
    {% endfor %}
</feed>

Symfony2 - Jour 13 - Sécurité
[Sommaire] Symfony2 - Jour 15 - Services Web >


Pour ce tutoriel, je me suis inspiré du tutoriel Symfony2 Jobeet du site IntelligentBee

Submit to DeliciousSubmit to DiggSubmit to FacebookSubmit to Google PlusSubmit to StumbleuponSubmit to TechnoratiSubmit to TwitterSubmit to LinkedIn