Ce tutoriel a été conçu pour vous guider pas à pas vers la maîtrise de Twig. Vous découvrirez ce qu’est Twig, à quoi il sert, ses avantages et ses limites, comment l’installer et l’utiliser dans un projet PHP (avec un exemple concret).
Ce tutoriel est présenté en plusieurs parties afin de rendre les explications digestes et pratiques. À la fin vous aurez un mini-projet fonctionnel et de bonnes bases pour utiliser Twig de manière efficace.
- Qu’est-ce que Twig et à quoi sert-il ?
- Avantages et limites de Twig
- Comment installer Twig étape par étape
- Syntaxe de base et exemples concrets
- Héritage de templates, blocs et includes
- Tests, filtres et fonctions avancées
- Extensions et filtres personnalisés (code complet)
- Sécurité : auto-escaping et bonnes pratiques
- Cache et performance
- Cas pratique : Un mini-blog étape par étape
- Recommandations
Qu’est-ce que Twig et à quoi sert-il ?
Twig est un moteur de templates pour PHP. Un moteur de templates permet de séparer la logique applicative (le code PHP) de la présentation (le HTML).
Twig fournit une syntaxe propre et lisible pour écrire des templates qui génèrent du HTML, du JSON ou tout autre format texte.
Twig sert essentiellement à rendre des vues plus lisibles et maintenables. En utilisant Twig, vous écrivez des fichiers .twig contenant du HTML et des balises Twig. Ces fichiers sont ensuite transformés en code PHP compilé par le moteur Twig, ce qui rend l’affichage rapide en production.
Twig est souvent utilisé avec des frameworks comme Symfony, mais il fonctionne très bien en dehors d’un framework, dans des applications PHP « maison ». Il apporte un niveau d’abstraction qui évite d’insérer du PHP pur dans les fichiers de présentation, ce qui améliore la lisibilité et la sécurité.
Avantages et limites de Twig
Twig propose plusieurs avantages majeurs.
Séparation claire entre logique et présentation. Les développeurs peuvent se concentrer sur la logique côté serveur, pendant que les designers/ intégrateurs travaillent sur les templates.
Syntaxe simple et expressive. La syntaxe de Twig utilise des accolades et des filtres lisibles. Vous pouvez écrire des boucles, conditions, et utiliser des filtres comme date, upper, escape.
Sécurité. Twig active l’auto-escaping HTML par défaut, ce qui réduit les risques d’injection de code côté client (XSS).
Performance. Les templates Twig sont compilés en PHP et mis en cache, ce qui donne de bonnes performances en production.
Extensibilité. Il est possible d’ajouter des filtres, fonctions et tags personnalisés via des extensions.
Twig a aussi des limites
Il n’est pas destiné à contenir de la logique métier lourde. Si vous mettez de la logique métier complexe dans vos templates, vous perdez la séparation des responsabilités.
Débogage. Parfois, le débogage d’un template peut être moins direct que le débogage d’un script PHP, surtout si la compilation a été mise en cache.
Fonctions restreintes. Certaines opérations très spécifiques nécessitent la création d’extensions en PHP, ce qui demande plus d’effort.
Pour la plupart des usages web classiques, Twig offre un excellent compromis entre sécurité, lisibilité et performances.
Comment installer Twig étape par étape
Voici comment installer Twig dans un projet PHP simple. Les étapes sont expliquées étape par étape.
Étape 1 : Avoir PHP et Composer installés sur votre machine. Composer est le gestionnaire de dépendances PHP. Si Composer n’est pas installé, installez-le depuis getcomposer.org.
Étape 2 : Créez un dossier pour votre projet. Par exemple, dans un terminal tapez :
mkdir mon-projet-twig
cd mon-projet-twig
Étape 3 : Initialisez Composer (facultatif mais pratique) :
composer init
Suivez les prompts pour créer un composer.json minimal.
Étape 4 : Installez Twig via Composer :
composer require twig/twig
Cette commande télécharge Twig et ses dépendances dans le dossier vendor. Composer met aussi en place l’autoloading.
Étape 5 : Créez une structure simple de projet :
mon-projet-twig/
vendor/ (géré par composer)
templates/ (vos fichiers .twig)
base.twig
index.twig
public/
index.php
composer.json (géré par composer)
Étape 6 : Créez le fichier public/index.php
pour tester Twig. Exemple complet de index.php
expliqué ligne par ligne :
<?php
require __DIR__ . '/../vendor/autoload.php';
// 1) Définir le loader qui indique où trouver les templates
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/../templates');
// 2) Créer l'environnement Twig
$twig = new \Twig\Environment($loader, [
'cache' => __DIR__ . '/../var/cache/twig', // facultatif en dev
'debug' => true,
]);
// 3) Préparer des variables pour le template
$data = [
'title' => 'Bienvenue sur mon site',
'items' => ['Article 1', 'Article 2', 'Article 3'],
];
// 4) Rendre (render) le template index.twig
echo $twig->render('index.twig', $data);
La première ligne charge l’autoload de Composer. Le loader indique le dossier où Twig cherchera les fichiers .twig. L’environnement accepte des options comme le cache (chemin) et le debug. Enfin, la méthode render() prend le nom du template et un tableau associatif de variables à rendre disponibles dans le template.
Étape 7 : Créez templates/index.twig
:
{% extends 'base.twig' %}
{% block title %}{{ title }}{% endblock %}
{% block body %}
<h1>{{ title }}</h1>
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endblock %}
Ce template étend base.twig
, définit un bloc title et un bloc body, affiche la variable title et parcourt la liste items.
Étape 8 : Créez templates/base.twig
:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}Mon site{% endblock %}</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
Ce fichier définit la structure HTML de base et des blocs réutilisables. L’héritage permet d’éviter la duplication du HTML de base.
Étape 9 : Lancez un serveur local pour tester. Dans le terminal, à la racine du projet :
php -S 127.0.0.1:8000 -t public
Puis ouvrez votre navigateur à l’adresse indiquée. Vous devriez voir votre page générée par Twig. Vous pouvez également le lancer depuis votre serveur MAMP ou XAMPP et y accéder depuis votre navigateur à une adresse tel que :
http://localhost:8888/mon-projet-twig/public/
Syntaxe de base et exemples concrets
Twig utilise trois délimiteurs principaux.
Double accolades pour l’affichage de variables et l’évaluation d’expressions courtes : {{ ... }}
.
Exemple : {{ title }}
affiche la valeur de la variable title
.
Accolades avec pourcentage pour les structures de contrôle et blocs : {% ... %}
.
Exemple : {% if condition %} ... {% endif %}
et {% for item in items %} ... {% endfor %}
.
Accolades pour les commentaires : {# ... #}
. Ces commentaires ne sont pas envoyés au navigateur.
Exemple simple d’affichage :
Bonjour {{ user.name }}.
Si user.name
vaut « Alice », le rendu sera « Bonjour Alice. ».
Condition :
{% if user.isAdmin %}
<p>Accès administrateur</p>
{% else %}
<p>Accès utilisateur</p>
{% endif %}
Boucle :
<ul>
{% for post in posts %}
<li>{{ post.title }} — publié le {{ post.date|date('d/m/Y') }}</li>
{% else %}
<li>Aucun article trouvé.</li>
{% endfor %}
</ul>
La clause else
après une boucle s’exécute si la collection est vide.
Filtres : les filtres sont appliqués avec le caractère pipe |
. Exemple : {{ name|upper }}
pour mettre la chaîne en majuscules. Le filtre date
formate des objets DateTime ou des timestamps.
Fonctions : Twig propose des fonctions prédéfinies comme range()
, cycle()
, include()
. Exemple : {{ range(1,5) }}
renvoie une représentation de la plage, mais on utilise plutôt for i in range(1,5)
.
Escaping : Twig échappe automatiquement les variables dans un template HTML. Pour désactiver l’échappement sur une variable safe, on peut utiliser le filtre |raw
, mais cela doit être fait avec précaution.
Héritage de templates, blocs et includes
L’héritage est un pilier de Twig. Il évite la duplication du code HTML. On crée un template de base (layout) et on laisse des blocs modifiables.
L’exemple de base.twig (déjà vu) et extension par index.twig.
Include : la balise include
permet d’insérer un fragment de template sans hériter.

Des formations informatique pour tous !
Débutant ou curieux ? Apprenez le développement web, le référencement, le webmarketing, la bureautique, à maîtriser vos appareils Apple et bien plus encore…
Formateur indépendant, professionnel du web depuis 2006, je vous accompagne pas à pas et en cours particulier, que vous soyez débutant ou que vous souhaitiez progresser. En visio, à votre rythme, et toujours avec pédagogie.
Découvrez mes formations Qui suis-je ?{% include 'partials/header.twig' %}
Ce mécanisme est utile pour des composants réutilisables.
Macros : les macros sont l’équivalent de fonctions réutilisables côté template. On définit une macro dans un fichier et on l’importe.
Exemple de macro :
{# templates/macros.twig #}
{% macro button(text, url) %}
<a href="{{ url }}" class="btn">{{ text }}</a>
{% endmacro %}
Utilisation :
{% import 'macros.twig' as ui %}
{{ ui.button('Voir', '/page') }}
Les blocs peuvent être imbriqués et redéfinis. Si un template enfant redéfinit un bloc, il remplace le contenu du bloc parent. Si vous souhaitez ajouter du contenu au bloc parent sans le remplacer, utilisez {{ parent() }}
.
Tests, filtres et fonctions avancées
Twig propose des tests pour vérifier des conditions simples. Exemple : is defined
, is empty
, is even
, is odd
:
{% if variable is defined and variable is not empty %}
{{ variable }}
{% endif %}
Filtres courants : escape
(ou e
), upper
, lower
, join
, split
, length
, date
, default
. Le filtre default
est pratique pour fournir une valeur si la variable n’existe pas :
{{ user.name|default('Invité') }}
Fonctions courantes : path()
et asset()
si Twig est utilisé avec Symfony, include()
, source()
pour récupérer le contenu brut d’un template, cycle()
pour alterner des valeurs dans une boucle.
Extensions et filtres personnalisés (code complet)
Lorsque vous avez besoin d’un filtre ou d’une fonction spécifique, vous pouvez créer une extension Twig en PHP. Voici un exemple complet d’extension qui ajoute un filtre slugify
.
Créez la classe suivante, par exemple src/Twig/AppExtension.php
:
<?php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class AppExtension extends AbstractExtension
{
public function getFilters()
{
return [
new TwigFilter('slugify', [$this, 'slugify']),
];
}
public function slugify(string $text): string
{
// Convertir les caractères spéciaux en ASCII
$text = iconv('UTF-8', 'ASCII//TRANSLIT', $text);
// Mettre en minuscules
$text = strtolower($text);
// Remplacer les caractères non alphanumériques par des tirets
$text = preg_replace('/[^a-z0-9]+/', '-', $text);
// Supprimer les tirets en début/fin
$text = trim($text, '-');
return $text;
}
}
Ensuite, enregistrez l’extension dans votre script d’initialisation Twig :
$twig->addExtension(new \App\Twig\AppExtension());
Utilisation dans un template :
{{ post.title|slugify }}
Explication : le filtre slugify
transforme un titre en slug utilisable dans une URL.
Sécurité : auto-escaping et bonnes pratiques
Twig échappe automatiquement les variables dans le contexte HTML, ce qui évite la plupart des failles XSS. Néanmoins quelques règles s’imposent.
N’utilisez |raw
que lorsque vous êtes certain que le contenu est sûr (par exemple contenu éditorial nettoyé). Si vous devez afficher du HTML généré par un utilisateur, nettoyez-le côté serveur avant de le rendre raw
.
Utilisez les tests is defined
et le filtre default
pour éviter les erreurs quand une variable manque.
Activez le mode sandbox si vous autorisez des templates tiers à être exécutés. Le sandbox restreint l’accès aux fonctions, filtres et objets.
Pour les formulaires et urls, utilisez des fonctions spécifiques du framework (par ex. path()
dans Symfony) pour éviter d’assembler des liens manuellement.
Cache et performance
Twig compile les templates en PHP et peut les stocker en cache pour accélérer le rendu. Dans l’exemple d’installation, l’option cache
indique le dossier où Twig écrit les fichiers compilés. En environnement de production, il est conseillé d’activer le cache et éventuellement de désactiver le mode debug.
Exemple de configuration performante :
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/../templates');
$twig = new \Twig\Environment($loader, [
'cache' => __DIR__ . '/../var/cache/twig',
'auto_reload' => false, // utile si vous n'éditez pas vos templates en production
'debug' => false,
]);
auto_reload
vérifie si les templates ont été modifiés et recompiles si nécessaire ; en production on peut le désactiver pour optimiser.
Si vous avez un grand volume de templates ou des templates lourds, le précompilage des templates lors du déploiement peut accélérer le premier rendu.
Cas pratique : Un mini-blog étape par étape
Objectif : Construire un mini-blog statique qui affiche une page d’accueil listant des articles et une page article. Le tutoriel explique la structure, chaque fichier et chaque ligne importante.
Étape 1 : Commençons par la structure du projet. Créez la structure suivante :
mini-blog/
vendor/
templates/
base.twig
home.twig
article.twig
partials/
header.twig
footer.twig
public/
index.php
data/
posts.php
composer.json
Étape 2 : Stockage des données (fichier data/posts.php). Créez un fichier PHP qui simule des articles :
<?php
return [
[
'id' => 1,
'title' => 'Premiers pas avec Twig',
'date' => new DateTime('2025-01-10'),
'content' => '<p>Twig est un moteur de templates pour PHP...</p>',
],
[
'id' => 2,
'title' => 'Utiliser Twig dans un projet simple',
'date' => new DateTime('2025-02-05'),
'content' => '<p>Voici un guide pratique pour démarrer...</p>',
],
];
On retourne un tableau d’articles. En production ces données viendraient d’une base de données.
Étape 3 : public/index.php (routeur simple)
<?php
require __DIR__ . '/../vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader(__DIR__ . '/../templates');
$twig = new \Twig\Environment($loader, [
'cache' => false,
'debug' => true,
]);
$posts = require __DIR__ . '/../data/posts.php';
// Récupérer l'ID de l'article via la query string, ex ?id=1
$id = isset($_GET['id']) ? (int) $_GET['id'] : null;
if ($id) {
$article = null;
foreach ($posts as $p) {
if ($p['id'] === $id) {
$article = $p;
break;
}
}
if (!$article) {
http_response_code(404);
echo $twig->render('home.twig', ['posts' => $posts, 'error' => 'Article introuvable']);
exit;
}
echo $twig->render('article.twig', ['post' => $article]);
} else {
echo $twig->render('home.twig', ['posts' => $posts]);
}
Ce script récupère la liste d’articles, vérifie la présence d’un paramètre id, et rend la page article ou la page d’accueil.
Étape 4 : templates/base.twig
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>{% block title %}Mini-blog{% endblock %}</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.post { margin-bottom: 20px; padding-bottom: 10px; border-bottom: 1px solid #ddd; }
</style>
</head>
<body>
{% include 'partials/header.twig' %}
<main>
{% block content %}{% endblock %}
</main>
{% include 'partials/footer.twig' %}
</body>
</html>
Étape 5 : templates/partials/header.twig
<header>
<h1><a href="/index.php">Mini-blog</a></h1>
</header>
Étape 6 : templates/home.twig
{% extends 'base.twig' %}
{% block title %}Accueil — Mini-blog{% endblock %}
{% block content %}
<h2>Articles récents</h2>
{% if error is defined %}
<p>{{ error }}</p>
{% endif %}
{% for post in posts %}
<article class="post">
<h3><a href="/index.php?id={{ post.id }}">{{ post.title }}</a></h3>
<p>Publié le {{ post.date|date('d/m/Y') }}</p>
</article>
{% else %}
<p>Aucun article pour le moment.</p>
{% endfor %}
{% endblock %}
Étape 7 : templates/article.twig
{% extends 'base.twig' %}
{% block title %}{{ post.title }} — Mini-blog{% endblock %}
{% block content %}
<article>
<h2>{{ post.title }}</h2>
<p>Publié le {{ post.date|date('d/m/Y') }}</p>
<div>
{{ post.content|raw }}
</div>
<p><a href="/index.php">Retour à l'accueil</a></p>
</article>
{% endblock %}
Étape 8 : Tester. Démarrez le serveur PHP :
php -S 127.0.0.1:8000 -t public
Ouvrez http://127.0.0.1:8000
pour voir la liste des articles et cliquez sur un titre pour afficher l’article.
Ce mini-blog montre l’usage de variables, boucles, filtres (date), includes, héritage et rendu de contenu HTML stocké dans les données. Le contenu HTML de post.content
est rendu avec |raw
ici car il provient d’un contenu de démonstration. En production, nettoyez toujours le HTML utilisateur.
Recommandations
Ne placez pas de logique métier complexe dans les templates. Les templates doivent se contenter de présentation et de logique d’affichage simple.
Préparez les données côté contrôleur. Par exemple, formatez les dates, assemblez les structures nécessaires, et envoyez aux templates des données prêtes à être affichées.
Utilisez l’héritage de templates pour centraliser le layout et les éléments partagés comme le header et le footer.
Évitez |raw
autant que possible. Si nécessaire, nettoyez le HTML côté serveur.
Organisez vos templates en dossiers (partials, components) pour faciliter la maintenance.
Activez le cache Twig en production et désactivez le en développement.
Utilisez des extensions pour les fonctionnalités communes (slugify, humanize, etc.) afin d’éviter de dupliquer du code dans les templates.
FAQ rapide
Que se passe-t-il si une variable n’est pas définie ?
Twig ne génère pas d’erreur fatale par défaut, mais il est préférable d’utiliser default()
ou is defined
pour prévenir des comportements inattendus.
Comment déboguer un template ?
Activez l’option debug
lors de la configuration de l’environnement Twig et utilisez dump()
dans les templates si le debug est activé.
Peut-on utiliser Twig pour générer du JSON ?
Oui. Twig génère du texte. Il suffit de produire un JSON valide dans le template ou d’encoder les données en PHP et de ne pas utiliser l’échappement HTML.
Est-il possible d’utiliser Twig côté client (JavaScript) ?
Il existe des ports de Twig pour JavaScript (par exemple twig.js), mais ils sont distincts de l’implémentation PHP et ont des limitations. Pour du rendu côté client, on utilise généralement des moteurs JS modernes ou API JSON.
Twig est un moteur de templates PHP solide, sécurisé et performant pour vos projets PHP. Il facilite la séparation entre la logique et la présentation, propose une syntaxe claire et de nombreuses fonctionnalités utiles (héritage, filtres, macros, extensions).
Dans ce tutoriel vous avez appris les bases : installation, configuration, syntaxe, héritage, filtres, extensions et un cas pratique complet pour démarrer. En suivant les bonnes pratiques évoquées, vous pourrez intégrer Twig dans vos projets et améliorer la maintenabilité et la sécurité de vos vues.