Symfony : – Les Gabarits et les Blocks

01:05:02

Lors de la navigation sur un site web classique, une structure commune se dégage souvent : des éléments comme l’en-tête, le menu ou le pied de page restent constants, tandis que le contenu principal change selon les pages.

Si chaque page utilisait un template distinct contenant ces éléments communs, cela poserait des problèmes de maintenance : une modification dans l’en-tête, par exemple, nécessiterait de modifier tous les templates. Cela va à l’encontre du principe DRY (Don’t Repeat Yourself).

C’est ici qu’interviennent les layouts, ou gabarits, qui permettent de factoriser le code commun en un seul endroit.

Définition des gabarits

Un layout est un gabarit utilisé comme base pour construire d’autres pages. Il sert de « moule » pour les templates enfants qui peuvent personnaliser ou compléter son contenu.

Par défaut, Symfony propose un layout minimal nommé

base.html.twig

, situé dans le répertoire

templates/

.

Exemple :

base.html.twig
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}Welcome!{% endblock %}</title>
        {% block stylesheets %}{% endblock %}
        {% block javascripts %}
            {% block importmap %}{{ importmap('app') }}{% endblock %}
        {% endblock %}
    </head>
    <body>
        {% block body %}{% endblock %}
    </body>
</html>
Dans cet exemple, plusieurs blocks Twig (comme title , stylesheets , javascripts , et body ) définissent des zones modifiables. Les blocs permettent aux templates enfants de personnaliser leur contenu tout en réutilisant la structure générale. Les blocks : zones personnalisables Les blocks sont des zones définies dans un template, que les templates enfants peuvent redéfinir ou compléter. Syntaxe pour définir un block : {% block nom_du_block %} Contenu du block {% endblock %} Exemple minimal : {% block title %}Page d'accueil{% endblock %} Les noms des blocks doivent être explicites (par exemple title , body , etc.), mais ils peuvent être choisis librement. Héritage de templates avec Twig Twig prend en charge l’héritage de templates, qui permet aux templates enfants de réutiliser le contenu d’un layout parent tout en apportant leurs propres modifications. Exemple d’héritage : 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 index(): Response { return $this->render('default/index.html.twig'); } } Template parent ( base.html.twig ) : <!DOCTYPE html> <html> <head> <title>{% block title %}Welcome!{% endblock %}</title> </head> <body> {% block body %}{% endblock %} </body> </html> Template enfant ( default/index.html.twig ) : {% extends 'base.html.twig' %} {% block body %} <h1>Bonjour !</h1> {% endblock %} Résultat généré : <!DOCTYPE html> <html> <head> <title>Welcome!</title> </head> <body> <h1>Bonjour !</h1> </body> </html> Ici, le contenu du block body dans le template enfant remplace celui du parent. Combiner contenu parent et enfant Twig permet aussi de compléter un block défini dans un template parent au lieu de le remplacer entièrement. Exemple : Compléter le contenu d’un block Template enfant : {% extends 'base.html.twig' %} {% block title %} {{ parent() }} - Page d'accueil {% endblock %} {% block body %} <h1>Bienvenue sur la page d'accueil</h1> <p>Contenu supplémentaire ici.</p> {% endblock %} Résultat généré : <!DOCTYPE html> <html> <head> <title>Welcome! - Page d'accueil</title> </head> <body> <h1>Bienvenue sur la page d'accueil</h1> <p>Contenu supplémentaire ici.</p> </body> </html> L’instruction {{ parent() }} insère le contenu original du block title avant d’ajouter le texte supplémentaire. Utilisation avancée : inclusion de JavaScript ou CSS spécifiques L’héritage de blocks est particulièrement utile pour ajouter des scripts ou des feuilles de styles spécifiques à une page. Exemple : Ajouter un script spécifique Template enfant : {% extends 'base.html.twig' %} {% block javascripts %} {{ parent() }} <script src="/js/custom.js"></script> {% endblock %} Organisation et extension des layouts Symfony permet d’ajouter plusieurs répertoires pour organiser vos layouts. Cette configuration se fait dans le fichier config/packages/twig.yaml . Exemple de configuration : twig: paths: 'admin/templates': 'admin' 'frontend/templates': 'frontend' Les templates dans ces répertoires peuvent être référencés avec des espaces de noms, par exemple : {% extends '@admin/dashboard.html.twig' %} Documentation Twig sur les blocks Documentation officielle Symfony sur Twig Cheatsheet Twig Les gabarits de pages et les blocks sont des outils essentiels pour créer des interfaces web modulaires et maintenables. En utilisant les layouts et l’héritage de templates, vous pouvez factoriser le code commun et personnaliser facilement le contenu des pages. Ces techniques, associées à la flexibilité de Twig, vous permettent de construire des sites web robustes et élégants.
par admin4460
Nom d'utilisateur Mot de passe Mot de passe oublié? Se connecter SuivreSuivreSuivreSuivreSuivre window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-L58BSN4YKD'); © 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\/4954\/et-divi-dynamic-tb-8564-tb-7217-tb-6415-4954-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":"87db64130d","subscription_failed":"Veuillez v\u00e9rifier les champs ci-dessous pour vous assurer que vous avez entr\u00e9 les informations correctes.","et_ab_log_nonce":"5e9a8fb1e0","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":"4954","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":"963937941b","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; }