Table des matières
Comme vous le savez, le contrôleur est responsable du traitement de chaque demande qui vient dans une application Symfony2. En réalité, le contrôleur délègue la plupart des lourds travaux à d'autres endroits afin que le code puisse être testé et réutilisé. Quand un contrôleur doit générer du code HTML, CSS ou tout autre contenu, il transmet le travail hors du moteur de template. Dans ce chapitre, vous allez apprendre à écrire des templates puissants qui peuvent être utilisées pour renvoyer le contenu à l'utilisateur, remplissez les organismes par courrier électronique, et plus encore. Vous apprendrez des raccourcis, des moyens astucieux pour étendre les templates et la façon de réutiliser le code du template.
Un template est tout simplement un fichier texte qui peut générer n'importe quel format basé sur du texte (HTML, XML, CSV, LaTeX ...). Le type le plus familier de template est un template de PHP - un fichier texte analysé par PHP, qui contient un mélange de texte et le code PHP:
<!DOCTYPE html> <html> <head> <title>Welcome to Symfony!</title> </head> <body> <h1><?php echo $page_title ?></h1> <ul id="navigation"> <?php foreach ($navigation as $item): ?> <li> <a href="<?php echo $item->getHref() ?>"> <?php echo $item->getCaption() ?> </a> </li> <?php endforeach; ?> </ul> </body> </html>
Mais les les paquets de Symfony2 contienne une langue encore plus puissante pour les gabarits appelés Twig. Twig vous permet d'écrire des templates concis qui sont lisibles pour les concepteurs de sites Web et, à plusieurs égards, plus puissant que les templates PHP:
<!DOCTYPE html> <html> <head> <title>Welcome to Symfony!</title> </head> <body> <h1>{{ page_title }}</h1> <ul id="navigation"> {% for item in navigation %} <li><a href="{{ item.href }}">{{ item.caption }}</a></li> {% endfor %} </ul> </body> </html>
Il y a une syntaxe tiers utilisés pour créer des commentaires: {# ceci est un commentaire #}. Cette syntaxe peut être utilisé sur plusieurs lignes, comme le PHP-équivalent / * commentaire * / syntaxe.
Twig contient également des filtres, qui modifient le contenu avant d'être rendu. Ce qui suit fait la variable titre tout en majuscules avant de le restituer:
{{Titre|upper}}
Twig est livré avec une longue liste de balises et filtres qui sont disponibles par défaut. Vous pouvez même ajouter vos propres extensions à Twig, au besoin.
L'enregistrement d'une extension de Twig est aussi facile que la création d'un nouveau service et le marquage avec des twig.extension tag .
Comme vous le verrez tout au long de la documentation, Twig prend également en charge les fonctions et de nouvelles fonctions peuvent être facilement ajoutés. Par exemple, les utilisations suivantes d'une norme pour la balise et la fonction du cycle d'imprimer dix balises div, avec une alternance de pair, impair classes:
{% for i in 0..10 %} <div class="{{ cycle(['odd', 'even'], i) }}"> <!-- some HTML here --> </div> {% endfor %}
Tout au long de ce chapitre, des exemples de templates sera montré à la fois dans Twig et PHP.
Les templates Twig sont destinés à être simple et ne traiteront pas de balises PHP. C'est par la conception: le système de template Twig est destiné à exprimer la présentation, pas la logique du programme. Plus vous utiliserez Twig, plus vous apprécierez et bénéficierez de cette distinction. Et bien sûr, vous serez aimé par les concepteurs Web.
Twig peut aussi faire des choses que PHP ne peut pas, comme l'héritage de vrai templates (Twig templates compile vers le bas pour les classes PHP qui héritent les uns des autres), les espaces de contrôle, bac à sable, et l'inclusion de fonctions et des filtres personnalisés qui s'appliquent uniquement aux templates. Twig contient des petits détails de fonctionnalités qui rende l'écriture des templates plus facile et plus concise. Prenons l'exemple suivant, qui combine une boucle avec une logique de si
<ul> {% for user in users %} <li>{{ user.username }}</li> {% else %} <li>No users found</li> {% endfor %} </ul>
Twig est rapide. Chaque template Twig est compilé en une classe PHP native qui est rendu à l'exécution. Les classes compilées sont situés dans le répertoire app/cache/{environment}/twig (où est l'environnement {environnement}, tels que dev ou prod) et, dans certains cas peut être utile pendant le débogage. Voir l'environnement dans la création de pages dans Symfony2 pour plus d'informations sur les environnements.
Lorsque le mode debug est activé (commun dans l'environnement de dev), une Twig template sera automatiquement recompilé lorsque des modifications sont apportées. Cela signifie qu'au cours du développement, vous pouvez heureusement apporter des modifications à un template de rameaux et de voir instantanément les modifications sans avoir à se soucier de compensation un cache.
Lorsque le mode debug est désactivé (commune dans l'environnement prod), cependant, vous devez effacer le répertoire de cache Twig de sorte que les templates Twig va régénérer. N'oubliez pas de faire cela lorsque vous déployez votre application.
Plus souvent qu'autrement, les templates dans un des éléments d'actions de projets communs, comme l'en-tête, pied de page, barre latérale ou plus. En Symfony2, nous aimons à penser à ce problème différemment: un template peut être décoré par un autre. Cela fonctionne exactement de la même façon que les classes PHP: héritage de templates vous permet de construire une base de "layout" template qui contient tous les éléments communs de votre site (définies comme des blocs pense "classe PHP avec des méthodes de base"). Un template enfant peut prolonger la mise en page de base et remplacer l'un de ses blocs (pensez à «sous-classe PHP qui l'emporte sur certaines méthodes de sa classe parent").
Tout d'abord, créer un fichier de configuration de base:
{# app/Resources/views/base.html.twig #} <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>{% block title %}Test Application{% endblock %}</title> </head> <body> <div id="sidebar"> {% block sidebar %} <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> {% endblock %} </div> <div id="content"> {% block body %}{% endblock %} </div> </body> </html>
<!-- app/Resources/views/base.html.php --> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title><?php $view['slots']->output('title', 'Test Application') ?></title> </head> <body> <div id="sidebar"> <?php if ($view['slots']->has('sidebar'): ?> <?php $view['slots']->output('sidebar') ?> <?php else: ?> <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> <?php endif; ?> </div> <div id="content"> <?php $view['slots']->output('body') ?> </div> </body> </html>
Bien que la discussion sur l'héritage template sera en termes de Twig, la philosophie est la même entre Twig et PHP templates.
Ce template définit le document squelette de base HTML d'une simple page à deux colonnes. Dans cet exemple, trois {% block %} zones sont définies (titre, barre latérale et corps). Chaque bloc peut être remplacé par un template de l'enfant ou à gauche avec sa mise en œuvre par défaut. Ce template pourrait également être rendu directement. Dans ce cas, les blocs de titre, la barre latérale et le corps conserveraient tout simplement les valeurs par défaut utilisées dans ce template.
Un template de l'enfant pourrait ressembler à ceci:
{# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {% extends '::base.html.twig' %} {% block title %}My cool blog posts{% endblock %} {% block body %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
<!-- src/Acme/BlogBundle/Resources/views/Blog/index.html.php --> <?php $view->extend('::base.html.php') ?> <?php $view['slots']->set('title', 'My cool blog posts') ?> <?php $view['slots']->start('body') ?> <?php foreach ($blog_entries as $entry): ?> <h2><?php echo $entry->getTitle() ?></h2> <p><?php echo $entry->getBody() ?></p> <?php endforeach; ?> <?php $view['slots']->stop() ?>
Le template parent est identifié par une syntaxe de chaîne spéciale (::base.html.twig) qui indique que le template vit dans le répertoire app/Resources/views du projet. Cette convention de nommage est expliquée en détail dans Naming template et emplacements.
La clé de l'héritage est le template de {%extends%} tag. Cela signifie que le moteur de templates évalue d'abord le template de base, qui met en place la mise en page et définit plusieurs blocs. Le template de l'enfant est alors rendue, à quel point le titre et le corps des blocs de la société mère sont remplacés par ceux de l'enfant. Selon la valeur de blog_entries, la sortie pourrait ressembler à ceci:
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>My cool blog posts</title> </head> <body> <div id="sidebar"> <ul> <li><a href="/">Home</a></li> <li><a href="/blog">Blog</a></li> </ul> </div> <div id="content"> <h2>My first post</h2> <p>The body of the first post.</p> <h2>Another post</h2> <p>The body of the second post.</p> </div> </body> </html>
Notez que le template enfant n'a pas à définir un bloc encadré, la valeur à partir du template parent est utilisé à la place. Le contenu avec un tag {% block %} dans un template de parent est toujours utilisé par défaut.
Vous pouvez utiliser autant de niveaux d'héritage que vous le souhaitez. Dans la section suivante, un template d'héritage commun à trois niveaux sera expliqué avec la façon dont les templates sont organisés à l'intérieur d'un projet Symfony2.
Lorsque vous travaillez avec l'héritage de template, voici quelques conseils à garder à l'esprit:
{% block sidebar %} <h3>Table of Contents</h3> ... {{ parent() }} {% endblock %}
Par défaut, les templates peuvent vivre dans deux endroits différents:
Symfony2 utilise la syntaxe bundle:controller:template pour les templates. Cela permet pour différents types de templates, que chacun existe dans un emplacement spécifique:
Dans la section Bundle Templates dérogatoire, vous allez découvrir comment chaque template existe à l'intérieur du AcmeBlogBundle, par exemple, peut être substituée en plaçant un template du même nom dans le répertoire app/Resources/AcmeBlogBundle/views/ . Cela donne le pouvoir d'outrepasser les templates de toute bundle vendor.
Espérons que la syntaxe de nommage template semble familier - c'est la même convention d'appellation utilisée pour désigner template de contrôleur de nommage .
Le bundle: contrôleur: format de template de chaque template spécifie l'endroit où le fichier de template est situé. Chaque nom de template dispose également de deux extensions qui spécifient le format et le moteur pour ce template.
Par défaut, n'importe quel template Symfony2 peut être écrit dans deux Twig ou PHP, et la dernière partie de l'extension (par exemple. Twig ou. Php) spécifie laquelle de ces deux moteurs doivent être utilisés. La première partie de l'extension, (par exemple. Html,. CSS, etc) est le format final que le gabarit doit produire. Contrairement au moteur, ce qui détermine la façon dont Symfony2 analyse le template, ce n'est tout simplement une tactique de l'organisation utilisé dans le cas de la même ressource doit être rendu au format HTML (index.html.twig), XML (index.xml.twig), ou de toute autre format. Pour plus d'informations, lire le débogage de l'article.
Les moteurs disponibles peuvent être configuré et même de nouveaux moteurs ajouté. Voir Configuration création de templates pour plus de détails.
Vous comprenez déjà comment sont nommés les bases de templates, et comment utiliser l'héritage de template. Les parties les plus dures sont déjà derrière vous. Dans cette section, vous apprendrez un grand groupe d'outils disponibles pour aider à effectuer les tâches les plus courantes de templates tels que notamment des templates d'autres, des liens vers des pages et y compris les images.
Symfony2 est livré avec plusieurs balises spécialisées Twig et des fonctions qui facilitent le travail du concepteur de template. En PHP, le système de templates fournit un système d'aide extensible qui fournit des fonctionnalités utiles dans un contexte de template.
Nous avons déjà vu quelques-uns intégré des balises Twig ({%block%} et {%extends%}) ainsi que d'un exemple d'un helper PHP ($view['slots']). Apprenons un peu plus.
Vous aurez souvent à inclure le même template ou un fragment de code sur plusieurs pages différentes. Par exemple, dans une application avec "articles de presse", le code du template affichant un article peut être utilisé sur la page détail de l'article, sur une page affichant les articles les plus populaires, ou dans une liste des derniers articles.
Lorsque vous avez besoin de réutiliser un morceau de code PHP, vous avez l'habitude de déplacer le code vers une nouvelle classe PHP ou une fonction. La même chose est vraie pour les templates. En déplaçant le code du template réutilisé dans son propre template, il peut être inclus à partir de n'importe quel autre template. Tout d'abord, créer le template que vous aurez besoin de les réutiliser.
{# src/Acme/ArticleBundle/Resources/views/Article/articleDetails.html.twig #} <h2>{{ article.title }}</h2> <h3 class="byline">by {{ article.authorName }}</h3> <p> {{ article.body }} </p>
<!-- src/Acme/ArticleBundle/Resources/views/Article/articleDetails.html.php --> <h2><?php echo $article->getTitle() ?></h2> <h3 class="byline">by <?php echo $article->getAuthorName() ?></h3> <p> <?php echo $article->getBody() ?> </p>
Y compris ce template à partir d'autre template est simple:
{# src/Acme/ArticleBundle/Resources/Article/list.html.twig #} {% extends 'AcmeArticleBundle::layout.html.twig' %} {% block body %} <h1>Recent Articles<h1> {% for article in articles %} {% include 'AcmeArticleBundle:Article:articleDetails.html.twig' with {'article': article} %} {% endfor %} {% endblock %}
<!-- src/Acme/ArticleBundle/Resources/Article/list.html.php --> <?php $view->extend('AcmeArticleBundle::layout.html.php') ?> <?php $view['slots']->start('body') ?> <h1>Recent Articles</h1> <?php foreach ($articles as $article): ?> <?php echo $view->render('AcmeArticleBundle:Article:articleDetails.html.php', array('article' = > $article)) ?> <?php endforeach; ?> <?php $view['slots']->stop() ?>
Le template est inclus en utilisant la balise {%include%}. Notez que le nom du template suit la même convention type. Le template articleDetails.html.twig utilise une variable article. Ceci est passé par le template list.html.twig utilisé avec la commande.
La syntaxe {'article': article} est la norme pour la syntaxe de hachage de Twig (c'est à dire un tableau avec des clés nommées). Si nous avions besoin de passer dans plusieurs éléments, il devrait ressembler à ceci: {'foo': foo, 'bar': bar}.
Dans certains cas, vous avez besoin de faire plus que d'inclure un template simple. Supposons que vous ayez une barre latérale dans votre mise en page qui contient les trois articles les plus récents. La récupération des trois articles peuvent comprendre l'interrogation de la base de données ou d'effectuer une autre logique lourde qui ne peut pas être fait à partir d'un template.
La solution consiste simplement à intégrer le résultat d'un contrôleur de toute une partie de votre template. Tout d'abord, créer un contrôleur qui rend un certain nombre d'articles récents:
// src/Acme/ArticleBundle/Controller/ArticleController.php class ArticleController extends Controller { public function recentArticlesAction($max = 3) { // make a database call or other logic to get the "$max" most recent articles $articles = ...; return $this->render('AcmeArticleBundle:Article:recentList.html.twig', array('articles' = > $articles)); } }
Le template recentList est parfaitement clair:
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {% for article in articles %} <a href="/article/{{ article.slug }}"> {{ article.title }} </a> {% endfor %}
<!-- src/Acme/ArticleBundle/Resources/views/Article/recentList.html.php --> <?php foreach ($articles as $article): ?> <a href="/article/<?php echo $article->getSlug() ?>"> <?php echo $article->getTitle() ?> </a> <?php endforeach; ?>
Remarquez que nous avons triché et codé en dur l'URL dans cet exemple l'article (par exemple /article /*slug*). C'est une mauvaise pratique. Dans la section suivante, vous allez apprendre à le faire correctement.
Pour inclure le contrôleur, vous aurez besoin de vous référer à l'aide de la syntaxe de la chaîne standard pour les contrôleurs (c'est à dire bundle:controller:action)
{# app/Resources/views/base.html.twig #} ... <div id="sidebar"> {% render "AcmeArticleBundle:Article:recentArticles" with {'max': 3} %} </div>
<!-- app/Resources/views/base.html.php --> ... <div id="sidebar"> <?php echo $view['actions']->render('AcmeArticleBundle:Article:recentArticles', array('max' = > 3)) ?> </div>
Chaque fois que vous trouvez que vous avez besoin d'une variable ou un élément d'information que vous n'avez pas accès à un template, compte rendu d'un contrôleur. Les contrôleurs sont rapides à exécuter et promouvoir l'organisation du bon code et la réutilisation.
Création de liens vers d'autres pages de votre application est l'un des emplois les plus courants pour un template. Au lieu de coder en dur dans les templates d'URL, utilisez le chemin Twig fonction (ou l'assistant routeur en PHP) pour générer des URL basée sur la configuration du routage. Plus tard, si vous souhaitez modifier l'URL d'une page en particulier, tout ce que vous devez faire est de changer la configuration du routage, les templates seront de générer automatiquement la nouvelle URL.
Tout d'abord, lien vers le "_welcome" la page, qui est accessible via la configuration suivante de routage:
_welcome: pattern: / defaults: { _controller: AcmeDemoBundle:Welcome:index }
<route id="_welcome" pattern="/"> <default key="_controller">AcmeDemoBundle:Welcome:index</default> </route>
$collection = new RouteCollection(); $collection->add('_welcome', new Route('/', array( '_controller' = > 'AcmeDemoBundle:Welcome:index', ))); return $collection;
Pour créer un lien vers la page, il suffit d'utiliser le chemin Twig fonction et se référer à la route:
<a href="{{ path('_welcome') }}">Home</a>
<a href="<?php echo $view['router']->generate('_welcome') ?>">Home</a>
Comme prévu, ce qui générera l'URL /. Voyons comment cela fonctionne avec une route plus compliquée:
article_show: pattern: /article/{slug} defaults: { _controller: AcmeArticleBundle:Article:show }
<route id="article_show" pattern="/article/{slug}"> <default key="_controller">AcmeArticleBundle:Article:show</default> </route>
$collection = new RouteCollection(); $collection->add('article_show', new Route('/article/{slug}', array( '_controller' = > 'AcmeArticleBundle:Article:show', ))); return $collection;
Dans ce cas, vous devez spécifier à la fois le nom de la route (article_show) et une valeur pour le paramètre {slug}. En utilisant cette voie, nous allons revoir le template recentList de la section précédente et un lien vers les articles correctement:
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {% for article in articles %} <a href="{{ path('article_show', { 'slug': article.slug }) }}"> {{ article.title }} </a> {% endfor %}
<!-- src/Acme/ArticleBundle/Resources/views/Article/recentList.html.php --> <?php foreach ($articles in $article): ?> <a href="<?php echo $view['router']->generate('article_show', array('slug' = > $article->getSlug()) ?>"> <?php echo $article->getTitle() ?> </a> <?php endforeach; ?>
Vous pouvez également générer une URL absolue en utilisant l'URL Twig fonction:
<a href="{{ url('_welcome') }}">Home</a>
La même chose peut être fait dans les templates de PHP en passant un troisième argument de la méthode generate ():
<a href="<?php echo $view['router']->generate('_welcome', array(), true) ?>">Home</a>
Templates également souvent référence à des images, Javascript, les feuilles de style et d'autres actifs. Bien sûr, vous pourriez coder en dur le chemin de ces actifs (par exemple /images/logo.png), mais Symfony2 offre une option plus dynamique par l'intermédiaire des actifs Twig fonction:
<img src="{{ asset('images/logo.png') }}" alt="Symfony!" /> <link href="{{ asset('css/blog.css') }}" rel="stylesheet" type="text/css" />
<img src="<?php echo $view['assets']->getUrl('images/logo.png') ?>" alt="Symfony!" /> <link href="<?php echo $view['assets']->getUrl('css/blog.css') ?>" rel="stylesheet" type="text/css" />
L'objectif principal du fonctionnement actif est de rendre votre application plus portable. Si votre application réside à la racine de votre hôte (par exemple http://example.com ), les chemins doivent être rendus /images/logo.png. Mais si vous avez vos applications dans un sous-répertoire (par exemple http://example.com/my_app ), chaque chemin actif doit rendre le sous-répertoire (par exemple /my_app/images/logo.png). La fonction prend en charge l'actif de ce en déterminant la façon dont votre application est utilisée et de générer les chemins corrects en conséquence.
En outre, si vous utilisez la fonction d'actifs, Symfony peut ajouter automatiquement une chaîne de requête à votre actif, afin de garantir que les mises à jour des actifs statiques ne sera pas mis en cache lorsqu'il est déployé. Par exemple, /images/logo.png pourrait ressembler /images/logo.png?V2. Pour plus d'informations, consultez le assets_version option de configuration.
Aucun site ne saurait être complèt sans inclure les fichiers Javascript et les feuilles de style. Dans Symfony, l'inclusion de ces actifs est géré avec élégance en tirant parti de l'héritage de template de Symfony.
Cette section vous apprendra la philosophie sous-jacente, y compris les actifs de feuilles de style et de Javascript dans Symfony. Symfony conditionne aussi une autre bibliothèque, appelée Assetic, qui suit cette philosophie, mais vous permet de faire des choses beaucoup plus intéressantes à ces actifs. Pour plus d'informations sur l'utilisation Assetic voir Comment utiliser Assetic pour Asset Management .
Commencez par ajouter deux blocs à votre template de base qui contiendra vos actifs: un style appelé à l'intérieur de la balise la tête et un autre javascripts disant juste au-dessus de la balise body de clôture. Ces blocs contiennent tous les styles et les Javascripts que vous aurez besoin tout au long de votre site:
{# 'app/Resources/views/base.html.twig' #} <html> <head> {# ... #} {% block stylesheets %} <link href="{{ asset('/css/main.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} </head> <body> {# ... #} {% block javascripts %} <script src="{{ asset('/js/main.js') }}" type="text/javascript"></script> {% endblock %} </body> </html>
C'est assez facile! Mais que faire si vous avez besoin d'inclure une feuille de style supplémentaire ou Javascript partir d'un template enfant? Par exemple, supposons que vous avez une page de contact et vous avez besoin d'inclure une feuille de style contact.css simplement sur cette page. De l'intérieur de template de cette page contact, procédez comme suit:
{# src/Acme/DemoBundle/Resources/views/Contact/contact.html.twig #} {% extends '::base.html.twig' %} {% block stylesheets %} {{ parent() }} <link href="{{ asset('/css/contact.css') }}" type="text/css" rel="stylesheet" /> {% endblock %} {# ... #}
Dans le template de l'enfant, il vous suffit de remplacer le bloc des feuilles de style et de mettre votre tag nouvelle feuille de style à l'intérieur de ce bloc. Bien sûr, puisque vous voulez ajouter au contenu du bloc parent (et pas vraiment le remplacer), vous devez utiliser le parent () Twig fonction de tout inclure dans le bloc des feuilles de style du template de base.
Vous pouvez également inclure les bundle situés dans les ressources de vos paquets Resources/public. Vous aurez besoin pour faire fonctionner les commandes php app/console assets:install target[—symlink] , qui se déplace (ou des liens symboliques) des fichiers dans l'emplacement correct. (La cible est par défaut "web").
<link href="{{ asset('bundles/acmedemo/css/contact.css') }}" type="text/css" rel="stylesheet" />
Le résultat final est une page qui inclut à la fois les feuilles de style et main.css contact.css.
Lors de chaque demande, Symfony2 fixera une application template global variable dans les deux Twig et moteurs de template PHP par défaut. La variable est une application GlobalVariables exemple qui vous donnera accès à certaines variables spécifiques à l'application automatique:
<p>Username: {{ app.user.username }}</p> {% if app.debug %} <p>Request method: {{ app.request.method }}</p> <p>Application Environment: {{ app.environment }}</p> {% endif %}
<p>Username: <?php echo $app->getUser()->getUsername() ?></p> <?php if ($app->getDebug()): ?> <p>Request method: <?php echo $app->getRequest()->getMethod() ?></p> <p>Application Environment: <?php echo $app->getEnvironment() ?></p> <?php endif; ?>
Vous pouvez ajouter vos propres variables globales de template mondiaux. Voir l'exemple sur le livre de recettes de variables globales .
Le cœur du système de template dans Symfony2 est le moteur de template. Cet objet spécial est chargé de rendre les templates et en retournant leur contenu. Lorsque vous rendez un template dans un contrôleur, par exemple, vous êtes en train d'utiliser le service moteur de templates. Par exemple:
return $this->render('AcmeArticleBundle:Article:index.html.twig');
équivaut à
$engine = $this->container->get('templating'); $content = $engine->render('AcmeArticleBundle:Article:index.html.twig'); return $response = new Response($content);
Le moteur de templates (ou "service") est préconfiguré pour fonctionner automatiquement à l'intérieur Symfony2. Il peut, bien sûr, être configuré en outre dans le fichier de configuration d'application:
# app/config/config.yml framework: # ... templating: { engines: ['twig'] }
<!-- app/config/config.xml -->
<framework:templating>
<framework:engine id="twig" />
</framework:templating>
// app/config/config.php $container->loadFromExtension('framework', array( // ... 'templating' = > array( 'engines' = > array('twig'), ), ));
Plusieurs options de configuration sont disponibles et sont couverts dans la configuration Annexe .
Le moteur de Twig est obligatoire pour utiliser le webprofiler (ainsi que de nombreux tiers faisceaux).
La communauté Symfony2 est fière de créer et de maintenir des bundles de haute qualité (voir KnpBundles.com ) pour un grand nombre de caractéristiques différentes. Une fois que vous utilisez un paquet tiers, vous aurez probablement besoin de passer outre et de personnaliser un ou plusieurs de ses templates.
Supposons que vous avez inclus l'imaginaire open-source AcmeBlogBundle dans votre projet (par exemple dans le répertoire src/Acme/BlogBundle). Et pendant que vous êtes vraiment heureux avec tout, vous souhaitez remplacer le blog "la liste" page pour personnaliser le balisage spécifiquement pour votre application. En creusant dans le contrôleur Blog de la AcmeBlogBundle, vous trouverez les éléments suivants:
public function indexAction() { $blogs = // some logic to retrieve the blogs $this->render('AcmeBlogBundle:Blog:index.html.twig', array('blogs' = > $blogs)); }
Lorsque le AcmeBlogBundle:Blog:index.html.twig est rendue, Symfony2 est en fait à deux endroits différents pour le template:
Pour remplacer le template bundle, il suffit de copier le template index.html.twig du faisceau dans app/Resources/AcmeBlogBundle/views/Blog/index.html.twig (le répertoire app/Resources/AcmeBlogBundle n'existera pas, de sorte que vous aurez besoin de le créer). Vous êtes maintenant libre de personnaliser le template.
Cette logique s'applique également aux templates de base de bundles. Supposons aussi que chaque template dans AcmeBlogBundle hérite d'un template de base appelé AcmeBlogBundle::layout.html.twig. Tout comme avant, Symfony2 se situera a deux endroits suivants pour le template:
Encore une fois, pour remplacer le template, il suffit de copier à partir du bundle dans app/Resources/AcmeBlogBundle/views/layout.html.twig. Vous êtes maintenant libre pour adapter cette copie comme bon vous semble.
Si vous prenez un peu de recul, vous verrez que Symfony2 commence toujours par examiner dans le fichier app/Resources/{BUNDLE_NAME}/views/ pour un template. Si le template n'existe pas là-bas, il continue en vérifiant à l'intérieur des Ressources et annuaire vues du bundle lui-même. Cela signifie que tous les templates de bundle peut être surchargée en les plaçant dans l'application correcte des ressources ou sous-répertoire.
Depuis le framework Symfony2 lui-même est juste un paquet, des templates de base peuvent être remplacés de la même manière. Par exemple, le noyau TwigBundle contient un certain nombre de différentes "exception" et "erreur" des templates qui peuvent être substituées en copiant chacune à partir des Resources/views/Exception de la TwigBundle vers vous l'aurez deviné, l'application app/Resources/TwigBundle/views/Exception.
Une façon courante d'utiliser l'héritage est d'utiliser une approche à trois niveaux. Cette méthode fonctionne parfaitement avec les trois différents types de templates que nous venons de découvrir
{# src/Acme/BlogBundle/Resources/views/layout.html.twig #} {% extends '::base.html.twig' %} {% block body %} <h1>Blog Application</h1> {% block content %}{% endblock %} {% endblock %}
Créer des templates individuels pour chaque page et étendre le template de section appropriée. Par exemple, l '«indice» à la page serait appelé quelque chose proche de AcmeBlogBundle:Blog:index.html.twig et la liste des messages de blog réels.
{# src/Acme/BlogBundle/Resources/views/Blog/index.html.twig #} {% extends 'AcmeBlogBundle::layout.html.twig' %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2> <p>{{ entry.body }}</p> {% endfor %} {% endblock %}
Notez que ce template s'étend du template de section (AcmeBlogBundle::layout.html.twig) qui étend elle-même la mise en page application de base (::base.html.twig). C'est le template d'héritage commun à trois niveaux.
Lors de la construction de votre application, vous pouvez choisir de suivre cette méthode ou tout simplement faire de chaque template de page d'étendre le template d'application de base directement (par exemple {%extends '::base.html.twig'%}). Le model à trois template est une des meilleures pratiques utilisées par des bundles vendor de sorte que le template de base pour un bundle peut être facilement remplacée pour bien étendre la disposition de base de votre application.
Lors de la génération du HTML à partir d'un template, il ya toujours un risque qu'une variable de template HTML peut émettre involontaire ou dangereux du code côté client. Le résultat est que le contenu dynamique pourrait se casser le code HTML de la page résultante ou permettre à un utilisateur malveillant d'effectuer une Cross Site Scripting (XSS) attaque. Considérons cet exemple classique:
Hello {{ name }}
Hello <?php echo $name ?>
Imaginez qu'un utilisateur entre le code suivant
<script>alert('hello!')</script>
Sans aucun échappement de sortie, le template résultant sera de provoquer un message d'alerte JavaScript pour faire apparaître:
Hello <script>alert('hello!')</script>
Et tandis que cela semble inoffensif, si un utilisateur peut en arriver là, ce même utilisateur devrait aussi être capable d'écrire JavaScript qui effectue des actions malveillantes à l'intérieur de la zone sécurisée d'un non-savoir, l'utilisateur légitime.
La réponse au problème est l'échappement de sortie. Avec la sortie d'échappement sur le même template rendra sans danger, et littéralement imprimer la balise de script à l'écran:
Hello <script>alert('helloe')</script>
Twig et PHP systèmes de templates abordent le problème de différentes manières. Si vous utilisez Twig, la sortie d'échappement est activée par défaut et vous êtes protégé. En PHP, output escaping n'est pas automatique; vous'll need à manually escape where necessary. Voir Sortie Échapper Twig
Si vous utilisez des templates de Twig, l'échappement de sortie est activé par défaut. Cela signifie que vous êtes protégé out-of-the-box des conséquences non intentionnelles de code soumis par les utilisateurs. Par défaut, la sortie échapper suppose que le contenu est échappé pour la sortie HTML.
Dans certains cas, vous devrez désactiver la sortie s'échapper lorsque vous effectuez le rendu d'une variable qui est digne de confiance et contient des balises qui ne doivent pas être échappé. Supposons que les utilisateurs administratifs sont en mesure de rédiger des articles qui contiennent du code HTML. Par défaut, Twig échapperont au corps de l'article. Pour le rendre normalement, ajouter le filtre brut: {{article.body|raw}}.
Vous pouvez également désactiver la production littérale l'intérieur d'un {% bloc %} de région ou pour un template tout entier. Pour plus d'informations, voir d'échappement de sortie dans la documentation Twig.
La sortie d'échappement est pas automatique lors de l'utilisation des templates de PHP. Cela signifie que si vous choisissez explicitement pour échapper à une variable, vous n'êtes pas protégé. Pour utiliser la sortie échapper, utilisez la méthode de view escape():
Hello <?php echo $view->escape($name) ?>
Par défaut, la méthode escape() suppose que la variable est rendu dans un contexte HTML (et donc la variable est échappé pour être sans danger pour HTML). Le second argument vous permet de changer le contexte. Par exemple, pour produire quelque chose dans une chaîne JavaScript, utilisez le contexte js:
var myMsg = 'Hello <?php echo $view->escape($name, 'js') ?>';
Nouveau dans la version 2.0.9: Cette fonctionnalité est disponible sous forme de Twig 1.5.x, qui a d'abord été livré avec Symfony 2.0.9.
Lorsque vous utilisez PHP, vous pouvez utiliser var_dump() si vous avez besoin de trouver rapidement la valeur d'une variable passée. Ceci est utile, par exemple, à l'intérieur de votre contrôleur. La même chose peut être réalisée lors de l'utilisation des Twig à l'aide de l'extension de débogage. Ce doit être activé dans la config:
# app/config/config.yml services: acme_hello.twig.extension.debug: class: Twig_Extension_Debug tags: - { name: 'twig.extension' }
<!-- app/config/config.xml --> <services> <service id="acme_hello.twig.extension.debug" class="Twig_Extension_Debug"> <tag name="twig.extension" /> </service> </services>
// app/config/config.php use Symfony\Component\DependencyInjection\Definition; $definition = new Definition('Twig_Extension_Debug'); $definition->addTag('twig.extension'); $container->setDefinition('acme_hello.twig.extension.debug', $definition);
Les paramètres de templates peuvent ensuite être sauvegardées en utilisant la fonction de vidage:
{# src/Acme/ArticleBundle/Resources/views/Article/recentList.html.twig #} {{ dump(articles) }} {% for article in articles %} <a href="/article/{{ article.slug }}"> {{ article.title }} </a> {% endfor %}
Les variables ne seront sous-évaluées si paramètre de débogage Twig (en config.yml) est vrai. Par défaut ce qui signifie que les variables seront déversés dans l'environnement de dev, mais pas la prod environnement.
Les templates sont un moyen générique pour rendre le contenu dans n'importe quel format. Et tandis que dans la plupart des cas, vous allez utiliser des templates pour rendre le contenu HTML, un template peut tout aussi bien générer le code JavaScript, CSS, XML ou tout autre format dont vous pouvez rêver.
Par exemple, le même «ressource» est souvent rendu dans plusieurs formats différents. Pour rendre une page d'index l'article au format XML, il suffit d'inclure le format dans le nom du template:
En réalité, ce n'est rien de plus qu'une convention de nommage et le template n'est pas effectivement rendus différemment en fonction de son format.
Dans de nombreux cas, vous voudrez peut-être pour permettre à un seul contrôleur pour rendre de multiples formats différents sur la base du «format de la demande". Pour cette raison, un motif commun est de faire ce qui suit:
public function indexAction() { $format = $this->getRequest()->getRequestFormat(); return $this->render('AcmeBlogBundle:Blog:index.'.$format.'.twig'); }
Le getRequestFormat sur les valeurs par défaut objet de requête html, mais peut renvoyer n'importe quel autre format basé sur le format demandé par l'utilisateur. Le format de la demande est le plus souvent gérés par le routage, où une route peut être configuré de sorte que /contact définit le format de demande de html, /contact.xml définit le format de XML. Pour plus d'informations, consultez l'exemple avancée dans le chapitre Routage
Pour créer des liens qui incluent le paramètre format, accompagné d'une clé dans le hachage _format paramètre:
<a href="{{ path('article_show', {'id': 123, '_format': 'pdf'}) }}"> PDF Version </a>
<a href="<?php echo $view['router']->generate('article_show', array('id' = > 123, '_format' = > 'pdf')) ?>"> PDF Version </a>
Le moteur de templates dans Symfony est un outil puissant qui peut être utilisé chaque fois que vous avez besoin de générer du contenu de présentation en HTML, XML ou tout autre format. Et si les templates sont un moyen courant pour générer du contenu dans un automate, leur utilisation n'est pas obligatoire. L'objet de réponse retourné par un contrôleur peut être créé avec ou sans l'utilisation d'un template:
// creates a Response object whose content is the rendered template $response = $this->render('AcmeArticleBundle:Article:index.html.twig'); // creates a Response object whose content is simple text $response = new Response('response content');
Le moteur de templates de symfony est très flexible et deux moteurs de rendu différents templates sont disponibles par défaut: les templates PHP traditionnels et les templates élégants et puissants Twig. La fois un soutien et une hiérarchie de template sont emballés avec un riche ensemble de fonctions d'assistance capables d'accomplir les tâches les plus courantes.
Dans l'ensemble, le thème de la création de templates devrait être considéré comme un outil puissant qui est à votre disposition. Dans certains cas, vous n'avez pas besoin de rendre un template, et en Symfony2, c'est absolument parfait.