DY

06 Twig

Maintenant que nous savons router nos fonctions PHP vers un pattern d'url (routing + Controller), il convient de s'intéresser au V de MVC à savoir les vues !

Des vues ?

Les vues (parfois nommés templates) permettent de séparer la présentation (le code HTML) de notre logique métier (le controller). Flight intégre un mécanisme de gestion des vues mais celui-ci est plutôt limité. Nous allons donc utiliser le moteur de templates du secteur PHP à savoir Twig.

Twig

Twig est un moteur de templates pour le langage de programmation PHP, utilisé par défaut par le framework Symfony. Celui-ci est une traduction de jinja, moteur de templates écrit en python ❤️.

Fonctionnalités
Syntaxe

Pour afficher le contenu d'une variable

{{ ma_variable }}

Pour afficher un élément d'un tableau ou d'un objet

{{ book.title }}

Pour itérer sur un tableau

{% for book in books %}
    {{ book.title }}
{% endfor %}

Et si on mélange tout ça avec du HTML ?

<ul>
{% for book in books %}
    <li>
        <strong>{{ book.title }}</strong>
    </li>
{% endfor %}
</ul>
Filtres

Les filtres fournissent des traitements sur une expression, si on les place après elle séparés par des pipes.

Variables spéciales

Donc, pour obtenir la route d'une page :

{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')) }}
Installation

Un composer require sur le package twig/twig ?

Mise en oeuvre

Initialisation

Pour commencer créer un répertoire views/ à la racine du projet.

Puis nous devons indiquer à Flight que nous allons utiliser Twig et le charger en extension mais tout d'abord nous devons charger Twig et le configurer.

Dans votre fichier index.php:

<?php

$loader = new \Twig\Loader\FilesystemLoader(dirname(__FILE__) . '/views');
$twigConfig = array(
    // 'cache' => './cache/twig/',
    // 'cache' => false,
    'debug' => true,
);

Une fois que nous avons charger et configurer Twig, il convient d'indiquer à Flight de l'inscrire en tant qu'extension

index.php:

<?php
Flight::register('view', '\Twig\Environment', array($loader, $twigConfig), function ($twig) {
    $twig->addExtension(new \Twig\Extension\DebugExtension()); // Add the debug extension
});

Désormais Flight sera en mesure d'utiliser Twig.

Notre première vue

Et maintenant nous allons utiliser Twig conjointement avec Flight pour générer notre page à partir d'une vue.

<?php
Flight::route('/first_view/', function(){
    Flight::view()->display('first_view.twig');
});

Félicitation vous venez de créer votre première vue et de la rendre via Twig.

Afficher des choses plus utiles ...

Afficher du HTML via Twig c'est bien, afficher le conteu de variables, tableaux, ... c'est encore mieux. Nous allons découvrir comment passé des données à notre vue.

En reprenant notre vue:

<?php
Flight::route('/first_view/', function(){
    Flight::view()->display('first_view.twig');
});

Nous allons la modifier, pour lui passer quelques données:

<?php
Flight::route('/first_view/', function(){
    $data = [
        'contenu' => 'Hello World!',
        'name' => 'Ben Kenobi',
    ];
    Flight::view()->display('first_view.twig', $data);
});

Nous passons à notre fichier twig le tableau data qui contient deux éléments. Si nous rechargons notre page nous ne voyons pas nos données apparaître. Il faut donc modifier notre fichier .twig pour afficher les données:

Ajoutez le code suivant à votre vue:

{{ contenu }}

{{ name }}
  1. Que constatez vous ?
  2. Avez vous compris le passage de données à notre vue ?

Héritage de template

La partie la plus puissante de Twig est l’héritage des templates. L'héritage de templates vous permet de créer un «squelette» de base contenant tous les éléments communs de votre site et définissant les blocs que les modèles enfants peuvent remplacer.

Cela semble compliqué mais reste très basique. Il est plus facile de comprendre cela en commençant par un exemple.

Template de base

Ce template, que nous appellerons base.twig, définit un simple squelette de document HTML que vous pouvez utiliser pour une page simple à deux colonnes. C’est le travail des templates «enfants» de remplir les blocs vides de contenu:

<!DOCTYPE html>
<html lang="en">
<head>
    {% block head %}
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}{% endblock %} - My Webpage</title>
    {% endblock %}
</head>
<body>
    <main>{% block content %}{% endblock %}</main>
    <footer>
        {% block footer %}
        &copy; Copyright 2008 by <a href="http://domain.invalid/">you</a>.
        {% endblock %}
    </footer>
</body>
</html>

Dans cet exemple, les balises {% block %} définissent quatre blocs que les modèles enfants peuvent remplir.

La balise de bloc indique simplement au moteur de gabarit qu'un modèle enfant peut remplacer les espaces réservés qu'il contient.

Template enfant

Un modèle enfant pourrait ressembler à ceci:

{% extends "base.twig" %}
{% block title %}Index{% endblock %}
{% block head %}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
    <h1>Index</h1>
    <p class="important">
      Welcome to my awesome homepage.
    </p>
{% endblock %}

La balise {% extend %} est la clé ici. Il indique au moteur de modèle que ce modèle «étend» un autre modèle. Lorsque le système de gabarit évalue ce gabarit, il localise d'abord le parent. La balise extend devrait être la première balise du modèle.

Global et filtre

Global

Parfois nous avons besoins de passer la même valeur à plusieurs voir toutes nos vues, Twig intégre un mécanisme très intéressant appellé global.

<?php
Flight::register('view', '\Twig\Environment', array($loader, $twigConfig), function ($twig) {
    $twig->addExtension(new \Twig\Extension\DebugExtension()); // Add the debug extension
    $twig->addGlobal('ma_valeur', "Hello There!");
});

Ainsi la variable ma_valeur sera passé à chaque vue, il est possible de rendre cela plus intéressant en passant des variables plus complexes, voir le résultat d'appel de fonction.

Filtres

Twig intégre de nombreux filtres par défaut, il est possible de créer nos propres filtres au besoin:

<?php
Flight::register('view', 'Twig_Environment', array($loader, $twigConfig), function ($twig) {
    // Twig loading treatment
    $twig->addFilter(new \Twig\TwigFilter('trad', function($string){
        return $string;
    }));
});

Il s'agit d'un filtre très intéressant qui retourne la valeur inchangée.. Le but est ici juste de vous présenter la syntaxe pour créer vos propres filtres.

Shortcut

Faire appel à Twig pour rendre nos templates c'est chouette, toutefois faire appel à cette ligne de code :

<?php
Flight::view()->display('first_view.twig');

Reste assez complexe. Et si nous utilisions un raccourci pour faire appel à cette fonction ?

Après l'enregistrement de Twig ajouter le code suivant:

<?php

Flight::map('render', function($template, $data=array()){
    Flight::view()->display($template, $data);
});

Ce code permet de dire que lorsque que nous ferons appel à la méthode render de Flight, nous utiliserons Twig.

Ainsi ceci:

<?php
Flight::route('/first_view/', function(){
    Flight::view()->display('first_view.twig');
});

Devient cela:

<?php
Flight::route('/first_view/', function(){
    Flight::render('first_view.twig');
});

Mise en application

En utilisant l'approche TDD, les Tests unitaires et d'intégrations

Pour aller plus loin

Vous avez encore à découvrir du monde des moteurs de template, comme par exemple Les structures de contrôles, ou encore l'escaping