URL rewriting avec "slugification" du titre d'un article - Symfony 2 partie 11

Tutorial Symfony 2 : Génération d'un "slug" à partir du titre de l'article afin d'avoir des urls optimisées pour les moteurs de recherche.

Publié le 02/10/2013

Nous allons générer un "slug" à partir du titre de l'article afin d'avoir des urls optimisées pour les moteurs de recherche.

1 - Mise à jour de l'entité Blog

Ajoutons une nouvelle propriété à l'entité Blog :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Entity/Blog.php 

Nous allons mettre à jour avec le contenu suivant :


// src/Blogger/BlogBundle/Entity/Blog.php

class Blog
{
    // ..

    /**
     * @ORM\Column(type="string")
     */
    protected $slug;

    // ..
}

2 - Génération des accesseurs et migration de la bdd

Avec les commandes suivantes, nous allons regénérer les accesseurs et migrer la base de données pour y ajouter le champ slug à la table blog :


php app/console doctrine:generate:entities Blogger
php app/console doctrine:migrations:diff
php app/console doctrine:migrations:migrate

3 - Génération de la valeur du slug

Pour générer la valeur du slug nous allons utiliser la methode slugify du tutoriel de Jobeet dans l'entité Blog :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Entity/Blog.php 

Nous allons ajouter la méthode suivante :


// src/Blogger/BlogBundle/Entity/Blog.php

public function slugify($text)
{
    // replace non letter or digits by -
    $text = preg_replace('#[^\\pL\d]+#u', '-', $text);

    // trim
    $text = trim($text, '-');

    // transliterate
    if (function_exists('iconv'))
    {
        $text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
    }

    // lowercase
    $text = strtolower($text);

    // remove unwanted characters
    $text = preg_replace('#[^-\w]+#', '', $text);

    if (empty($text))
    {
        return 'n-a';
    }

    return $text;
}

Nous allons ensuite nous servir de cette méthode dans le set et le get de title de l'entité Blog :

sudo nano /var/www/symblog/src/Blogger/BlogBundle/Entity/Blog.php 

Nous allons mettre à jour comme suit :


// src/Blogger/BlogBundle/Entity/Blog.php

public function setTitle($title)
{
    $this->title = $title;

    $this->setSlug($this->title);

    return $this;
}

public function setSlug($slug)
{
    $this->slug = $this->slugify($slug);
}

Maintenant on recharge les données factices via les fixtures pour générer les slugs des articles :

php app/console doctrine:fixtures:load 

4 - Mise à jour des routes générées

Editer le fichier suivant :

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

Nous allons mettre à jour comme suit :


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

{% extends 'BloggerBlogBundle::layout.html.twig' %}

{% block body %}
    {% for blog in blogs %}
        <article class="blog">
            <div class="date"><time datetime="{{ blog.created|date('c') }}">{{ blog.created|date('l, F j, Y') }}</time></div>
            <header>
                <h2><a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id, 'slug': blog.slug }) }}">{{ blog.title }}</a></h2>
            </header>

            <img src="{{ asset(['images/', blog.image]|join) }}" />
            <div class="snippet">
                <p>{{ blog.blog(500) }}</p>
                <p class="continue"><a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id, 'slug': blog.slug }) }}">Continue reading...</a></p>
            </div>

            <footer class="meta">
                <p>Comments: <a href="{{ path('BloggerBlogBundle_blog_show', { 'id': blog.id, 'slug': blog.slug }) }}#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>
        </article>
    {% else %}
        <p>There are no blog entries for symblog</p>
    {% endfor %}
{% endblock %}

On va procéder de la même manière dans le template sidebar :

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

Nous allons mettre à jour comme suit :


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

{# .. #}

<a href="{{ path('BloggerBlogBundle_blog_show', { 'id': comment.blog.id, 'slug': comment.blog.slug }) }}#comment-{{ comment.id }}">
    {{ comment.blog.title }}
</a>

{# .. #}

On va ensuite modifier l'action createAction() du CommentController :

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

Nous allons mettre à jour comme suit :


// src/Blogger/BlogBundle/Controller/CommentController.php

public function createAction($blog_id)
{
    // ..

    if ($form->isValid()) {
        // ..

        return $this->redirect($this->generateUrl('BloggerBlogBundle_blog_show', array(
            'id'    => $comment->getBlog()->getId(),
            'slug'  => $comment->getBlog()->getSlug())) .
            '#comment-' . $comment->getId()
        );
    }

    // ..
}

Vous pouvez maintenant constater en naviguant que les urls sont bien enrichies.