Contactez-nous

Inclusion de fragments de templates (`include`)

Découvrez comment utiliser la fonction `include` de Twig pour insérer des fragments de templates réutilisables (partiels) dans vos vues Symfony. Optimisez la modularité et la maintenabilité de vos templates.

Introduction à l'inclusion de templates : modulariser vos vues

En complément de l'héritage de templates, Twig offre un autre mécanisme puissant pour favoriser la réutilisabilité et la modularité de vos vues : l'inclusion de templates avec la fonction ou le tag include. Alors que l'héritage est idéal pour définir une structure globale (layout) que plusieurs pages partagent et spécialisent, l'inclusion est parfaite pour insérer des morceaux de templates plus petits et autonomes (souvent appelés "partiels" ou "fragments") à différents endroits de vos vues principales ou même à l'intérieur d'autres partiels.

Pensez à des éléments d'interface utilisateur qui se répètent fréquemment mais qui ne font pas nécessairement partie de la structure de base d'un layout : un formulaire de recherche, une liste de produits similaires, un encart d'informations utilisateur, un menu de navigation complexe, etc. Au lieu de dupliquer le code HTML et Twig pour ces éléments dans chaque template où ils apparaissent, vous pouvez les isoler dans leur propre fichier de template et les inclure là où c'est nécessaire.

L'utilisation de include rend vos templates principaux plus concis, plus lisibles et plus faciles à maintenir. Si vous devez modifier un fragment, vous ne le faites qu'à un seul endroit, et la modification est répercutée partout où ce fragment est inclus.

Syntaxe et utilisation de base de `include`

La fonction include de Twig permet d'insérer le contenu rendu d'un autre template à l'endroit où elle est appelée. Sa syntaxe la plus simple est :

{{ include('chemin/vers/mon_fragment.html.twig') }}

Ou en utilisant la syntaxe de tag (les deux sont équivalentes en termes de fonctionnalité de base) :

{% include 'chemin/vers/mon_fragment.html.twig' %}

Le chemin vers le template fragment est relatif au répertoire templates/ de votre projet Symfony. Il est courant de stocker ces fragments dans un sous-répertoire dédié, par exemple templates/fragments/ ou templates/_partials/ (le tiret bas est une convention pour indiquer qu'il s'agit de fichiers non destinés à être rendus directement par une route).

Exemple :

Supposons que vous ayez un fragment pour afficher un message de bienvenue, templates/fragments/_welcome_message.html.twig :

{# templates/fragments/_welcome_message.html.twig #}
<div class="alert alert-info">
    <p>Bienvenue sur notre site ! Découvrez nos dernières offres.</p>
</div>

Vous pouvez l'inclure dans votre template principal, par exemple templates/page/accueil.html.twig :

{% extends 'base.html.twig' %}

{% block title %}Accueil{% endblock %}

{% block body %}
    {{ include('fragments/_welcome_message.html.twig') }}

    <h1>Contenu principal de la page d'accueil</h1>
    <!-- ... reste du contenu ... -->
{% endblock %}

Lorsque page/accueil.html.twig sera rendu, le contenu de fragments/_welcome_message.html.twig sera inséré à l'endroit de l'appel à include.

Passer des variables au template inclus

Par défaut, un template inclus a accès à toutes les variables du contexte dans lequel il est appelé (c'est-à-dire les variables disponibles dans le template qui fait l'inclusion). Cependant, il est souvent préférable de passer explicitement les variables dont le fragment a besoin. Cela rend le fragment plus autonome, plus facile à comprendre (ses dépendances sont claires) et plus réutilisable dans différents contextes où les variables globales pourraient ne pas être les mêmes.

Pour passer des variables spécifiques à un template inclus, vous pouvez utiliser l'option with, en fournissant un tableau associatif où les clés sont les noms des variables dans le fragment et les valeurs sont les données à passer :

{# Dans le template appelant #}
{{ include('fragments/_user_profile_card.html.twig', { 
    'user_name': utilisateur.nomComplet, 
    'user_avatar_url': utilisateur.avatarUrl, 
    'user_bio': utilisateur.biographie 
}) }}

{# Ou avec la syntaxe de tag #}
{% include 'fragments/_user_profile_card.html.twig' with {
    'user_name': utilisateur.nomComplet,
    'user_avatar_url': utilisateur.avatarUrl,
    'user_bio': utilisateur.biographie
} %}

Le template fragment templates/fragments/_user_profile_card.html.twig pourra alors utiliser les variables user_name, user_avatar_url, et user_bio :

{# templates/fragments/_user_profile_card.html.twig #}
<div class="user-card">
    <img src="{{ user_avatar_url | default(asset('images/default_avatar.png')) }}" alt="Avatar de {{ user_name }}">
    <h3>{{ user_name }}</h3>
    {% if user_bio is defined and user_bio is not empty %}
        <p>{{ user_bio | slice(0, 100) }}...</p>
    {% endif %}
</div>

Si vous souhaitez que le template inclus n'ait accès uniquement aux variables que vous lui passez explicitement (et non à celles du contexte appelant), vous pouvez ajouter le mot-clé only :

{# Le fragment n'aura accès qu'à 'item_data' et pas aux autres variables du template appelant #}
{{ include('fragments/_item_display.html.twig', { 'item_data': produit }, with_context = false) }}
{# En syntaxe de tag, le mot-clé 'only' est plus direct #}
{% include 'fragments/_item_display.html.twig' with { 'item_data': produit } only %}

Utiliser only (ou with_context = false pour la fonction) est une bonne pratique pour créer des fragments véritablement encapsulés et éviter des dépendances cachées au contexte global.

Utilisations avancées et bonnes pratiques

La fonction include offre quelques options supplémentaires pour des cas d'usage plus spécifiques :

  • Gestion des templates manquants : Par défaut, si le template spécifié dans include n'est pas trouvé, Twig lèvera une erreur. Vous pouvez rendre l'inclusion optionnelle en utilisant le mot-clé ignore missing. Si le template est manquant, Twig l'ignorera silencieusement (rien ne sera inclus).
{% include 'fragments/_optional_banner.html.twig' ignore missing %}

{# Ou avec la fonction #}
{{ include('fragments/_optional_banner.html.twig', ignore_missing = true) }}

Ceci est utile pour des fonctionnalités optionnelles ou des personnalisations qui pourraient ne pas toujours être présentes.

  • Inclusion conditionnelle : Vous pouvez combiner include avec une instruction if pour n'inclure un fragment que si une certaine condition est remplie.
{% if utilisateur.estAdministrateur %}
    {{ include('fragments/_admin_tools_menu.html.twig') }}
{% endif %}

Bonnes pratiques pour l'utilisation de include :

  • Petits fragments ciblés : Les templates inclus devraient être relativement petits et se concentrer sur un aspect spécifique de l'interface.
  • Passez les données explicitement : Privilégiez l'utilisation de with { ... } only pour rendre vos fragments autonomes et leurs dépendances claires.
  • Organisez vos fragments : Utilisez des sous-répertoires (par exemple, templates/fragments/, templates/product/_partials/) pour ranger vos fragments de manière logique.
  • Ne pas abuser : Bien que include soit puissant, une décomposition excessive en micro-fragments peut parfois rendre la structure globale plus difficile à suivre. Trouvez le bon équilibre.
  • Pensez aux macros pour des éléments HTML très répétitifs : Pour des éléments HTML très structurés et répétitifs avec une logique interne (comme la génération de champs de formulaire ou d'éléments de menu complexes), les macros Twig peuvent être une alternative ou un complément à include.

En combinant judicieusement l'héritage (extends, block) pour la structure globale et l'inclusion (include) pour les composants réutilisables, vous pouvez créer des systèmes de templates Twig très organisés, maintenables et efficaces dans vos applications Symfony.