Ajout de la barre latérale avec nuages de tag et derniers commentaires - Symfony 2 partie 10

Tutorial Symfony 2 : Ajout d'une barre latérale comprenant un nuage de mots clés et les derniers commentaires.

Publié le 02/10/2013

Nous allons ajouter une barre latérale comprend un nuage de mots clés et les derniers commentaires.

1 - Affichage du nombre de commentaires sur la page d'accueil

Nous allons récupérer les données de la base de données par le controller Page :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/Page/index.html.twig 

Nous allons mettre à jour avec le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}

{# .. #}

<footer class="meta">
    <p>Comments: {{ blog.comments|length }}</p>
    <p>Posted by <span class="highlight">{{ blog.author }}</span> at {{ blog.created|date('h:iA') }}</p>
    <p>Tags: <span class="highlight">{{ blog.tags }}</span></p>
</footer>

{# .. #}

Nous pouvons voir maintenant apparaître sur la page d'accueil le nombre de commentaires par article.

2 - Mise à jour de notre requête getLatestBlogs()

Nous allons mettre à jour la requête du dépôt de l'entité Blog afin d'attacher les commentaires aux articles pour éviter le lazy loading de Doctrine et avoir de meilleurs performances : dans ce cas on va passer de six requêtes à une seule. Vous trouverer plus d'info sur le lazy laoding sur le tutorielorginal.

sudo nano /var/www/src/Blogger/BlogBundle/Repository/BlogRepositoy.php 

Nous allons mettre à jour avec le contenu suivant :


// src/Blogger/BlogBundle/Repository/BlogRepositoy.php

public function getLatestBlogs($limit = null)
{
    $qb = $this->createQueryBuilder('b')
               ->select('b, c')
               ->leftJoin('b.comments', 'c')
               ->addOrderBy('b.created', 'DESC');

    if (false === is_null($limit))
        $qb->setMaxResults($limit);

    return $qb->getQuery()
              ->getResult();
}

3 - Modification de template de la page d'accueil

Nous allons ajouter un lien vers l'affichage de commentaires de l'article :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/Page/index.html.twig 

Nous allons mettre à jour avec le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/Page/index.html.twig #}

{# .. #}

<footer class="meta">
    <p>Comments: <a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id }) }}#comments">{{ blog.comments|length }}</a></p>
    <p>Posted by <span class="highlight">{{ blog.author }}</span> at {{ blog.created|date('h:iA') }}</p>
    <p>Tags: <span class="highlight">{{ blog.tags }}</span></p>
</footer>

{# .. #}

4 - Ajout d'un nuage de tags à la bare latérale

Dans la classe BlogRepository, nous allons créer des nouvelles méthodes afin de récupérer les informations sur les mots clés pour notre nuage.

On va éditer le fichier suivant :

sudo nano /var/www/src/symblog/Blogger/BlogBundle/Repository/BlogRepository.php 

Nous allons mettre à jour avec le contenu suivant :


// src/Blogger/BlogBundle/Repository/BlogRepository.php

public function getTags()
{
    $blogTags = $this->createQueryBuilder('b')
                     ->select('b.tags')
                     ->getQuery()
                     ->getResult();

    $tags = array();
    foreach ($blogTags as $blogTag)
    {
        $tags = array_merge(explode(",", $blogTag['tags']), $tags);
    }

    foreach ($tags as &$tag)
    {
        $tag = trim($tag);
    }

    return $tags;
}

public function getTagWeights($tags)
{
    $tagWeights = array();
    if (empty($tags))
        return $tagWeights;

    foreach ($tags as $tag)
    {
        $tagWeights[$tag] = (isset($tagWeights[$tag])) ? $tagWeights[$tag] + 1 : 1;
    }
    // Shuffle the tags
    uksort($tagWeights, function() {
        return rand() > rand();
    });

    $max = max($tagWeights);

    // Max of 5 weights
    $multiplier = ($max > 5) ? 5 / $max : 1;
    foreach ($tagWeights as &$tag)
    {
        $tag = ceil($tag * $multiplier);
    }

    return $tagWeights;
}

Pour Afficher le nuage de tag, créer une nouvelle action dans le controller Page :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Controller/PageController.php 

Nous allons mettre à jour avec le contenu suivant :


// src/Blogger/BlogBundle/Controller/PageController.php

public function sidebarAction()
{
    $em = $this->getDoctrine()
               ->getManager();

    $tags = $em->getRepository('BloggerBlogBundle:Blog')
               ->getTags();

    $tagWeights = $em->getRepository('BloggerBlogBundle:Blog')
                     ->getTagWeights($tags);

    return $this->render('BloggerBlogBundle:Page:sidebar.html.twig', array(
        'tags' => $tagWeights
    ));
}

On va ensuite créer la vue pour la sidebar :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Controller/PageController.php 

Et ajouter le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}

Tag Cloud

{% for tag, weight in tags %} {{ tag }} {% else %} 
There are no tags
{% endfor %} 

Ajout du template sidebar dans le layout principal :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/layout.html.twig 

Mettre à jour avec le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}

{# .. #}

{% block sidebar %}
    {% render(controller('BloggerBlogBundle:Page:sidebar')) %}
{% endblock %}

Ajout des css de la sidebar :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/public/css/sidebar.css 

Ajouter le contenu suivant :

.sidebar .section { margin-bottom: 20px; } .sidebar h3 { line-height: 1.2em; font-size: 20px; margin-bottom: 10px; font-weight: normal; background: #eee; padding: 5px; } .sidebar p { line-height: 1.5em; margin-bottom: 20px; } .sidebar ul { list-style: none } .sidebar ul li { line-height: 1.5em } .sidebar .small { font-size: 12px; } .sidebar .comment p { margin-bottom: 5px; } .sidebar .comment { margin-bottom: 10px; padding-bottom: 10px; } .sidebar .tags { font-weight: bold; } .sidebar .tags span { color: #000; font-size: 12px; } .sidebar .tags .weight-1 { font-size: 12px; } .sidebar .tags .weight-2 { font-size: 15px; } .sidebar .tags .weight-3 { font-size: 18px; } .sidebar .tags .weight-4 { font-size: 21px; } .sidebar .tags .weight-5 { font-size: 24px; } 

Puis ajouter un lien dans le layout principal pour les styles ajoutés :

Ajout des css de la sidebar :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/layout.html.twig 

Ajouter le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/layout.html.twig #}

{# .. #}

{% block stylesheets %}
    {{ parent() }}
    <link href="{{ asset('bundles/bloggerblog/css/blog.css') }}" type="text/css" rel="stylesheet" />
    <link href="{{ asset('bundles/bloggerblog/css/sidebar.css') }}" type="text/css" rel="stylesheet" />
{% endblock %}

{# .. #}

Attention : Si vous n’avez pas utilisé les liens symboliques pour référencer les fichiers externes dans le répertoire web, vous devrez relancer la commande suivante afin mettre à jour les fichiers css :

php app/console assets:install web 

Vous devez maintenant voir s'afficher le nuage de tags sur la page d'accueil.

5 - Ajout des derniers commentaires à la bare latérale

Nous allons d'abord récuperer les derniers commentaires en créant une nouvelle requête dans la classe CommentRepository :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Repository/CommentRepository.php 

Ajouter la methode suivante :


<?php
// src/Blogger/BlogBundle/Repository/CommentRepository.php

public function getLatestComments($limit = 10)
{
    $qb = $this->createQueryBuilder('c')
                ->select('c')
                ->addOrderBy('c.id', 'DESC');

    if (false === is_null($limit))
        $qb->setMaxResults($limit);

    return $qb->getQuery()
              ->getResult();
}

On va maintenant mettre à jour l'action sidebar dans notre controller Page afin qu'il puisse récupérer les données pour les transmettre à la vue :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Controller/PageController.php 

Mettre à jour avec le contenu suivant :


// src/Blogger/BlogBundle/Controller/PageController.php

public function sidebarAction()
{
    // ..

    $commentLimit   = $this->container
                           ->getParameter('blogger_blog.comments.latest_comment_limit');
    $latestComments = $em->getRepository('BloggerBlogBundle:Comment')
                         ->getLatestComments($commentLimit);

    return $this->render('BloggerBlogBundle:Page:sidebar.html.twig', array(
        'latestComments'    => $latestComments,
        'tags'              => $tagWeights
    ));
}

On va ensuite créer un paramètre blogger_blog.comments.latest_comment_limit dans le fichier config.yml :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/config/config.yml 

Mettre à jour avec le contenu suivant :


# src/Blogger/BlogBundle/Resources/config/config.yml

parameters:
    # ..

    # Blogger max latest comments
    blogger_blog.comments.latest_comment_limit: 10

Puis on va fournir un affichage de ces commentaires dans la sidebar :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig 

Mettre à jour avec le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}

{# .. #}

<section class="section">
    <header>
        <h3>Latest Comments</h3>
    </header>
    {% for comment in latestComments %}
        <article class="comment">
            <header>
                <p class="small"><span class="highlight">{{ comment.user }}</span> commented on
                    <a href="{{ path('BloggerBlogBundle_blog_show', { 'id': comment.blog.id }) }}#comment-{{ comment.id }}">
                        {{ comment.blog.title }}
                    </a>
                    [<em><time datetime="{{ comment.created|date('c') }}">{{ comment.created|date('Y-m-d h:iA') }}</time></em>]
                </p>
            </header>
            <p>{{ comment.comment }}</p>
            </p>
        </article>
    {% else %}
        <p>There are no recent comments</p>
    {% endfor %}
</section>

On va pouvoir afficher dans la sidebar sur la home les derniers commentaires.

6 - Formatages des dates avec les extensions Twigg

Nous allons formater nos dates à l'aide des extensions de Twigg. Pour ce faire nous allons créer les dossiers et un fichier comme suit :


sudo mkdir /var/www/symblog/src/Blogger/BlogBundle/Twig/
sudo mkdir /var/www/symblog/src/Blogger/BlogBundle/Twig/Extensions
sudo nano /var/www/symblog/src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogExtension.php

Et ajouter le contenu suivant :


<?php
// src/Blogger/BlogBundle/Twig/Extensions/BloggerBlogExtension.php

namespace Blogger\BlogBundle\Twig\Extensions;

class BloggerBlogExtension extends \Twig_Extension
{
    public function getFilters()
    {
        return array(
            'created_ago' => new \Twig_Filter_Method($this, 'createdAgo'),
        );
    }

    public function createdAgo(\DateTime $dateTime)
    {
        $delta = time() - $dateTime->getTimestamp();
        if ($delta < 0)
            throw new \Exception("createdAgo is unable to handle dates in the future");

        $duration = "";
        if ($delta < 60)
        {
            // Seconds
            $time = $delta;
            $duration = $time . " second" . (($time > 1) ? "s" : "") . " ago";
        }
        else if ($delta <= 3600)
        {
            // Mins
            $time = floor($delta / 60);
            $duration = $time . " minute" . (($time > 1) ? "s" : "") . " ago";
        }
        else if ($delta <= 86400)
        {
            // Hours
            $time = floor($delta / 3600);
            $duration = $time . " hour" . (($time > 1) ? "s" : "") . " ago";
        }
        else
        {
            // Days
            $time = floor($delta / 86400);
            $duration = $time . " day" . (($time > 1) ? "s" : "") . " ago";
        }

        return $duration;
    }

    public function getName()
    {
        return 'blogger_blog_extension';
    }
}

Enregistrement de l'extension :

On va modifier le fichier services.yml comme suit : sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/config/services.yml

Et ajouter le contenu suivant :


services:
    blogger_blog.twig.extension:
        class: Blogger\BlogBundle\Twig\Extensions\BloggerBlogExtension
        tags:
            - { name: twig.extension }

On va pouvoir ensuite modifier la vue :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig 

Et ajouter le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/Page/sidebar.html.twig #}

{# .. #}

<section class="section">
    <header>
        <h3>Latest Comments</h3>
    </header>
    {% for comment in latestComments %}
        {# .. #}
        <em><time datetime="{{ comment.created|date('c') }}">{{ comment.created|created_ago }}</time></em>
        {# .. #}
    {% endfor %}
</section>

On peut maintenant constater le changement de format de date dans les commentaires présents dans la sidebar.

On va aussi mettre à jour les commentaires de la page d'affichage des articles afin d'y utiliser le filtre :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Resources/views/Comment/index.html.twig 

Et ajouter le contenu suivant :


{# src/Blogger/BlogBundle/Resources/views/Comment/index.html.twig #}

{% for comment in comments %}
    <article class="comment {{ cycle(['odd', 'even'], loop.index0) }}" id="comment-{{ comment.id }}">
        <header>
            <p><span class="highlight">{{ comment.user }}</span> commented <time datetime="{{ comment.created|date('c') }}">{{ comment.created|created_ago }}</time></p>
        </header>
        <p>{{ comment.comment }}</p>
    </article>
{% else %}
    <p>There are no comments for this post. Be the first to comment...</p>
{% endfor %}