Archives de
Tag: twig

Ecrire une extension pour twig dans symfony [FR]

Ecrire une extension pour twig dans symfony [FR]

Le but de cet article est d’expliquer comment écrire une fonction pour twig dans symfony. Je pars du principe que vous avez déjà un bundle avec des entités, dans mon cas se sera une entité News.

La première étape est de définir le service dans le fichier services.xml:

<services>
        <service id="dayo.twig.dayo_news_extension" class="Dayo\NewsBundle\Twig\NewsExtension">
            <tag name="twig.extension" />
            <argument type="service" id="service_container" />
        </service>
    </services>

Ici nous définissons un service dayo.twig.dayo_news_extension qui a pour tag twig.extension et qui prend pour paramètre le conteneur de services. Ce conteneur nous sera utile pour faire les requêtes à la base de données et rendre les templates.

Du côté du code de l’extension à proprement parler, il nous faut hériter de Twig_Extension  et surcharger deux méthodes: getFunctions()  afin de déclarer nos fonctions et getName() .

<?php

namespace Dayo\NewsBundle\Twig;

use Symfony\Component\DependencyInjection\ContainerInterface;

class NewsExtension extends \Twig_Extension
{
    public function getFunctions()
    {
        return array(
            //'displayNewsHomepage' => new \Twig_Function_Method($this, 'displayNewsHomepage'), // twig <= 1.11
            new \Twig_SimpleFunction('displayNewsHomepage', array($this, 'displayNewsHomepage')), // twig >= 1.12
        );
    }

    public function displayNewsHomepage($num)
    {
        return 'mon resultat';
    }

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

La façon de déclarer une fonction Twig change avec la version 1.12, j’ai donc mis l’ancienne et la nouvelle version. L’ancienne fonctionne toujours. Nous déclarons donc la fonction displayNewsHomepage qui renvoie une chaine de caractères.

Pour le moment nous ne servons pas du conteneur de services, apportons les modifications afin de pour l’utiliser.

private $container;

    public function __construct(ContainerInterface $container) {
        $this->container = $container;
    }

Modifions la fonction displayNewsHomepage pour récupérer les news et retourner le contenue du fichier twig.

public function displayNewsHomepage($num)
    {
        $news = $this->container->get('doctrine')
            ->getRepository('DayoNewsBundle:News')
            ->findForHomepage($num);

        return $this->container->get('templating')->render('DayoNewsBundle:Twig:newsHomePage.html.twig', array('news' => $news));
    }

On récupère le repository de notre puis on récupère les derniers news avec la fonction personnelle findForHomepage($num). Enfin, pour retourner le code html on utilise la fonction render du service twig. Le template na rien de compliqué:

{% for n in news %}
        <h2>{{ n.title }}</h2>
        <p>{{ n.content }}</p>
{% endfor %}

L’appelle à notre fonction Twig se fait simplement de la manière suivante : {{ displayNewsHomepage(4) }}

Dans l’état actuel du code, le rendu ne sera pas celui voulu. En effet, Twig va échapper la valeur de retour de notre fonction, il faut spécifier que nous fessons confiance à la valeur de retour lors de la déclaration de notre fonction.

'displayNewsHomepage' => new \Twig_Function_Method($this, 'displayNewsHomepage',array("is_safe" => array("html"))), // twig <= 1.11
new \Twig_SimpleFunction('displayNewsHomepage', array($this, 'displayNewsHomepage'),array("is_safe" => array("html"))), // twig >= 1.12

Le code retourner par notre fonction n’est alors plus échappé.