Symfony : – Le moteur de templates Twig

13:25:27

Twig est un moteur de templates puissant et flexible, conçu pour gérer la couche de présentation dans les applications basées sur le modèle MVC. Il permet de séparer clairement la logique métier de la vue en regroupant tout le code lié à la présentation dans des fichiers spécifiques, appelés templates.

Contrairement à du simple HTML, ces templates peuvent inclure des instructions dynamiques écrites dans un langage spécifique à Twig, souvent désigné comme du « Twig ».

  • Origine : Créé en 2008 par Armin Ronacher, Twig s’inspire fortement du moteur de templates Jinja (utilisé en Python).
  • Intégration : Twig est maintenant maintenu par l’équipe Symfony et est le moteur de templates par défaut du framework.
  • Site officiel : https://twig.symfony.com

Pourquoi Twig ?

Une question légitime serait de demander : pourquoi Twig et non PHP directement ? Voici quelques raisons qui rendent Twig incontournable dans les projets Symfony :

  1. Performances élevées : Twig compile ses templates en code PHP pur, mis en cache pour éviter de recalculer à chaque requête.
  2. Sécurité renforcée : Les sorties sont protégées par défaut contre les attaques comme le Cross-Site Scripting (XSS).
  3. Syntaxe adaptée aux templates : Twig offre des fonctionnalités et des raccourcis spécifiques qui simplifient la création de vues complexes, tout en gardant un code lisible.
  4. Communauté et support : Twig est largement adopté, et la plupart des bundles et ressources Symfony reposent sur lui.

Mise en pratique : Twig en action

Exemple de base : un contrôleur et un template

Prenons un exemple simple où un contrôleur rend une vue via Twig.

Contrôleur :

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class DefaultController extends AbstractController
{
    #[Route("/")]
    public function hello(): Response
    {
        return $this->render('default/hello.html.twig');
    }
}
Template Twig ( templates/default/hello.html.twig ) : Hello world! Dans cet exemple : Le contrôleur utilise la méthode render() pour retourner une réponse basée sur un template Twig. Le fichier de template est situé dans le dossier templates/ , suivant la convention Symfony. Organisation des templates Les fichiers Twig sont placés dans le répertoire templates/ par convention. Ce répertoire peut être organisé en sous-dossiers : Templates généraux : templates/base.html.twig pour les gabarits globaux. Templates spécifiques aux contrôleurs : un dossier dédié pour chaque contrôleur. Exemple de structure : templates/ ├── base.html.twig ├── default/ └── hello.html.twig └── admin/ └── dashboard.html.twig Extensions et organisation avancée Symfony permet d’ajouter d’autres répertoires pour organiser les templates. Cela se fait via la configuration dans config/packages/twig.yaml . Exemple : twig: paths: 'admin/templates': 'admin' 'backend/templates': 'back' Dans cet exemple, les répertoires admin/templates et backend/templates sont ajoutés avec des espaces de noms respectifs @admin et @back . Les fichiers sont alors référencés comme suit : {% include '@admin/index.html.twig' %} Syntaxe et fonctionnalités de Twig Twig offre une syntaxe lisible et intuitive. Voici quelques exemples de base : a) Variables <p>{{ variable }}</p> b) Boucles {% for item in items %} <p>{{ item }}</p> {% endfor %} c) Conditions {% if user.isAdmin %} <p>Bienvenue, admin !</p> {% else %} <p>Bienvenue, utilisateur.</p> {% endif %} d) Inclusions {% include 'header.html.twig' %} Remarques sur l’utilisation Twig, comme tout autre composant Symfony, est un service accessible à travers le conteneur de services. La méthode render() du contrôleur est un exemple d’utilisation de ce service. Annotation @Template Le bundle SensioFrameworkExtraBundle permet une autre approche pour utiliser Twig. L’annotation @Template simplifie le rendu en permettant à Symfony de deviner le template basé sur le nom du contrôleur et de l’action. Exemple : namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\Routing\Annotation\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; class DefaultController extends AbstractController { /** * @Route("/") * @Template */ public function hello() { return ['name' => 'John']; } } Le template attendu ici sera default/hello.html.twig . Ressources utiles Documentation officielle Twig Documentation Symfony sur Twig Cheatsheet Twig Twig est bien plus qu’un simple moteur de templates : c’est un outil conçu pour améliorer la lisibilité, la sécurité et les performances des vues dans une application Symfony. Son adoption massive et sa parfaite intégration avec Symfony en font un choix incontournable pour les développeurs cherchant à créer des interfaces web élégantes et efficaces.
par admin4460
Nom d'utilisateur Mot de passe Mot de passe oublié? Se connecter © MyCreaNet 2025 Mentions légales Plan du site Gestion des cookies Accessibilité
{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"\/*"},{"not":{"href_matches":["\/wp-*.php","\/wp-admin\/*","\/wp-content\/uploads\/*","\/wp-content\/*","\/wp-content\/plugins\/*","\/wp-content\/themes\/Divi\/*","\/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-snippets-library-btns-wrap:before, .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-buttons-wrapper:before { content: "\45"; font-size: 27px; color: #ccffcc; font-family: ETModules; cursor: pointer; width: 28px; height: 27px; border-radius: 3px; padding-top: 1px; background-color: rgb(255, 255, 255, 0.2) !important; } .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-fb-form__group:nth-of-type(4) { display: none; } jQuery(document).ready(function($) { $(document).on('click', '.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-snippets-library-btns-wrap, .et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .et-code-buttons-wrapper', function(event) { if (event.target !== event.currentTarget) { return; // Exit the function if the click is on a child element } var firstEditor = $('.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .CodeMirror').get(0)?.CodeMirror; if (!firstEditor) { return; } $('.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] textarea[name="code_to_render"]').click(); // Enable hidden codemirror var secondEditor = $('.et-fb-form__toggle[data-name="et_pb_db_php_code_main_content"] .CodeMirror').get(1)?.CodeMirror; if (!secondEditor) { return; } var content = firstEditor.getValue(); // Add a random nonce as the first line of content to prevent caching var nonce = Math.random().toString(36).substring(2, 15); content = '/* nonce:' + nonce + ' */\n' + content; secondEditor.setValue(content); }); }); (function() { var file = ["https:\/\/mycreanet.fr\/wp-content\/et-cache\/4952\/et-divi-dynamic-tb-8749-tb-7217-tb-6415-4952-late.css"]; var handle = document.getElementById('divi-style-inline-inline-css'); var location = handle.parentNode; if (0===document.querySelectorAll('link[href="' + file + '"]').length) { var link = document.createElement('link'); link.rel = 'stylesheet'; link.id = 'et-dynamic-late-css'; link.href = file; location.insertBefore(link, handle.nextSibling); } })(); var et_link_options_data = [{"class":"et_pb_post_title_0_tb_header","url":"https:\/\/mycreanet.fr\/dashboard\/","target":"_self"},{"class":"et_pb_code_0_tb_header","url":"https:\/\/mycreanet.fr\/work\/","target":"_self"}]; /* <![CDATA[ */ wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } ); /* ]]> */ /* <![CDATA[ */ ( function( domain, translations ) { var localeData = translations.locale_data[ domain ] || translations.locale_data.messages; localeData[""].domain = domain; wp.i18n.setLocaleData( localeData, domain ); } )( "contact-form-7", {"translation-revision-date":"2025-02-06 12:02:14+0000","generator":"GlotPress\/4.0.1","domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural-forms":"nplurals=2; plural=n > 1;","lang":"fr"},"This contact form is placed in the wrong place.":["Ce formulaire de contact est plac\u00e9 dans un mauvais endroit."],"Error:":["Erreur\u00a0:"]}},"comment":{"reference":"includes\/js\/index.js"}} ); /* ]]> */ /* <![CDATA[ */ var wpcf7 = { "api": { "root": "https:\/\/mycreanet.fr\/wp-json\/", "namespace": "contact-form-7\/v1" } }; /* ]]> */ /* <![CDATA[ */ var tocplus = {"smooth_scroll":"1","visibility_show":"Afficher","visibility_hide":"Masquer","width":"Auto"}; /* ]]> */ /* <![CDATA[ */ var DIVI = {"item_count":"%d Item","items_count":"%d Items"}; var et_builder_utils_params = {"condition":{"diviTheme":true,"extraTheme":false},"scrollLocations":["app","top"],"builderScrollLocations":{"desktop":"app","tablet":"app","phone":"app"},"onloadScrollLocation":"app","builderType":"fe"}; var et_frontend_scripts = {"builderCssContainerPrefix":"#et-boc","builderCssLayoutPrefix":"#et-boc .et-l"}; var et_pb_custom = {"ajaxurl":"https:\/\/mycreanet.fr\/wp-admin\/admin-ajax.php","images_uri":"https:\/\/mycreanet.fr\/wp-content\/themes\/Divi\/images","builder_images_uri":"https:\/\/mycreanet.fr\/wp-content\/themes\/Divi\/includes\/builder\/images","et_frontend_nonce":"207e628c75","subscription_failed":"Veuillez v\u00e9rifier les champs ci-dessous pour vous assurer que vous avez entr\u00e9 les informations correctes.","et_ab_log_nonce":"3d8dc6054b","fill_message":"S'il vous pla\u00eet, remplissez les champs suivants:","contact_error_message":"Veuillez corriger les erreurs suivantes :","invalid":"E-mail non valide","captcha":"Captcha","prev":"Pr\u00e9c\u00e9dent","previous":"Pr\u00e9c\u00e9dente","next":"Prochaine","wrong_captcha":"Vous avez entr\u00e9 le mauvais num\u00e9ro dans le captcha.","wrong_checkbox":"Case \u00e0 cocher","ignore_waypoints":"no","is_divi_theme_used":"1","widget_search_selector":".widget_search","ab_tests":[],"is_ab_testing_active":"","page_id":"4952","unique_test_id":"","ab_bounce_rate":"5","is_cache_plugin_active":"no","is_shortcode_tracking":"","tinymce_uri":"https:\/\/mycreanet.fr\/wp-content\/themes\/Divi\/includes\/builder\/frontend-builder\/assets\/vendors","accent_color":"#006666","waypoints_options":[]}; var et_pb_box_shadow_elements = []; /* ]]> */ /* <![CDATA[ */ var DiviBlogExtrasFrontendData = {"ajaxurl":"https:\/\/mycreanet.fr\/wp-admin\/admin-ajax.php","ajax_nonce":"f107b17322","et_theme_accent_color":"#006666"}; /* ]]> */ /* <![CDATA[ */ var wpcf7_recaptcha = { "sitekey": "6LdTHXQrAAAAACmbbt7TJPkqCEfzcO8TdF_cEKX-", "actions": { "homepage": "homepage", "contactform": "contactform" } }; /* ]]> */ .wptpa_song_infrmtn, .wptpa_currenttime, .wptpa_duration, .wptpa_song, .wptpa_dwn_cnt, .wptpa_play_cnt, .wptpa_num, .wptpa_h2, .wptpa_ads{ font-family: 'Roboto', sans-serif; } .wptpa_player { background: #FFFFFF !important; } .wptpa_heading:before, .wptpa_heading:after { background: #000000 !important; } .wptpa_song_infrmtn { color: #000000 !important; } .wptpa_btn .wptpa_icon { fill: #555555; } .wptpa_btn.actv .wptpa_icon, .wptpa_btn:hover .wptpa_icon{ fill: #00D084; } .wptpa_btn:before{ background: #555555 !important; } .wptpa_player .wptpa_seek, .wptpa_player .wptpa_loader { background: #FFDA48 !important; } .wptpa_player .wptpa_seek span, .wptpa_progress { background: #CF2E2E !important; } .wptpa_ads, .wptpa_currenttime, .wptpa_duration { color: #FFFFFF !important; } .wptpa_volume_seek:before { background: #FFDA48 !important; } .wptpa_volume_value { background: #CF2E2E !important; } .wptpa_pllst_itm { border-bottom: 1px solid rgba(255, 255, 255, 0.25) !important; background: #23C5A3 !important; color: #000000 !important; } .wptpa_pllst_itm.crrnt, .wptpa_pllst_itm:hover { background: #FFDA48 !important; color: #000000 !important; } .wptpa_pllst_itm:last-child { border-bottom: 0px solid rgba(255, 255, 255, 0.25) !important; } .wptpa_bars, .wptpa_bars:before, .wptpa_bars:after{ background: #000000 !important; } .wptpa_line { border-color: #000000 !important; } .wptpa_pllst_itm .wptpa_icon { fill: #000000; } .wptpa_dwn_cnt, .wptpa_play_cnt { color: #000000 !important; } .wptpa_scroll_bar { background: #000000 !important; }