Reworded all the docs related to templates and Twig

This commit is contained in:
Javier Eguiluz
2019-09-05 13:19:29 +02:00
parent 7cb2585367
commit ec618e12df
30 changed files with 1298 additions and 1967 deletions

View File

@@ -446,3 +446,13 @@
/form/action_method /forms
/reference/requirements /setup
/bundles/inheritance /bundles/override
/templating /templates
/templating/escaping /templates
/templating/syntax /templates
/templating/debug /templates
/templating/render_without_controller /templates
/templating/app_variable /templates
/templating/formats /templates
/templating/namespaced_paths /templates
/templating/embedding_controllers /templates
/templating/inheritance /templates

View File

@@ -57,6 +57,8 @@ which is almost equivalent to the more verbose, but also more flexible,
$_SERVER
);
.. _accessing-request-data:
Accessing Request Data
~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -28,8 +28,8 @@ Usage
.. seealso::
This article explains how to use the Templating features as an independent
component in any PHP application. Read the :doc:`/templating` article to
learn about how to work with templates in Symfony applications.
component in any PHP application. Read the article about :doc:`templates </templates>`
to learn about how to work with templates in Symfony applications.
The :class:`Symfony\\Component\\Templating\\PhpEngine` class is the entry point
of the component. It needs a
@@ -211,5 +211,5 @@ Learn More
:glob:
/components/templating/*
/templating
/templates
/templating/*

View File

@@ -123,6 +123,8 @@ new kernel.
.. index::
single: Configuration; Debug mode
.. _debug-mode:
Debug Mode
~~~~~~~~~~

View File

@@ -179,7 +179,7 @@ object for you::
return $this->render('lucky/number.html.twig', ['number' => $number]);
Templating and Twig are explained more in the
:doc:`Creating and Using Templates article </templating>`.
:doc:`Creating and Using Templates article </templates>`.
.. index::
single: Controller; Accessing services
@@ -461,7 +461,8 @@ and then redirects. The message key (``notice`` in this example) can be anything
you'll use this key to retrieve the message.
In the template of the next page (or even better, in your base layout template),
read any flash messages from the session using ``app.flashes()``:
read any flash messages from the session using the ``flashes()`` method provided
by the :ref:`Twig global app variable <twig-app-variable>`:
.. code-block:: html+twig
@@ -650,7 +651,7 @@ handle caching and more.
Keep Going!
-----------
Next, learn all about :doc:`rendering templates with Twig </templating>`.
Next, learn all about :doc:`rendering templates with Twig </templates>`.
Learn more about Controllers
----------------------------
@@ -658,7 +659,7 @@ Learn more about Controllers
.. toctree::
:hidden:
templating
templates
.. toctree::
:maxdepth: 1

View File

@@ -206,9 +206,9 @@ Request Events, Checking Types
------------------------------
A single page can make several requests (one master request, and then multiple
sub-requests - typically by :doc:`/templating/embedding_controllers`). For the core
Symfony events, you might need to check to see if the event is for a "master" request
or a "sub request"::
sub-requests - typically when :ref:`embedding controllers in templates <templates-embed-controllers>`).
For the core Symfony events, you might need to check to see if the event is for
a "master" request or a "sub request"::
// src/EventListener/RequestListener.php
namespace App\EventListener;

View File

@@ -8,5 +8,5 @@ Getting Started
/page_creation
/routing
/controller
/templating
/templates
/configuration

View File

@@ -114,8 +114,8 @@ independently of the rest of the page::
In this example, the full-page cache has a lifetime of ten minutes.
Next, include the news ticker in the template by embedding an action.
This is done via the ``render`` helper (see :doc:`/templating/embedding_controllers`
for more details).
This is done via the ``render()`` helper (for more details, see how to
:ref:`embed controllers in templates <templates-embed-controllers>`).
As the embedded content comes from another page (or controller for that
matter), Symfony uses the standard ``render`` helper to configure ESI tags:

View File

@@ -532,7 +532,7 @@ a simple application. Along the way, you've made a simple routing
system and a method using ``ob_start()`` and ``ob_get_clean()`` to render
templates. If, for some reason, you needed to continue building this "framework"
from scratch, you could at least use Symfony's standalone
:doc:`Routing </components/routing>` component and :doc:`Twig </templating>`,
:doc:`Routing </components/routing>` component and :doc:`Twig </templates>`,
which already solve these problems.
Instead of re-solving common problems, you can let Symfony take care of

View File

@@ -291,7 +291,7 @@ create an event subscriber to set it automatically::
Twig: HTML & CSS
----------------
The Mime component integrates with the :doc:`Twig template engine </templating>`
The Mime component integrates with the :ref:`Twig template engine <twig-language>`
to provide advanced features such as CSS style inlining and support for HTML/CSS
frameworks to create complex HTML email messages. First, make sure Twig is installed:

View File

@@ -251,8 +251,8 @@ Now you may wonder where the Web Debug Toolbar has gone: that's because there is
no ``</body>`` tag in the current template. You can add the body element yourself,
or extend ``base.html.twig``, which contains all default HTML elements.
In the :doc:`/templating` article, you'll learn all about Twig: how to loop, render
other templates and leverage its powerful layout inheritance system.
In the :doc:`templates </templates>` article, you'll learn all about Twig: how
to loop, render other templates and leverage its powerful layout inheritance system.
Checking out the Project Structure
----------------------------------
@@ -304,7 +304,7 @@ Ok, time to finish mastering the fundamentals by reading these articles:
* :doc:`/routing`
* :doc:`/controller`
* :doc:`/templating`
* :doc:`/templates`
* :doc:`/configuration`
Then, learn about other important topics like the

View File

@@ -5,8 +5,8 @@ Twig Configuration Reference (TwigBundle)
=========================================
The TwigBundle integrates the Twig library in Symfony applications to
:doc:`render templates </templating>`. All these options are configured under
the ``twig`` key in your application configuration.
:ref:`render templates <templates-rendering>`. All these options are configured
under the ``twig`` key in your application configuration.
.. code-block:: terminal
@@ -41,8 +41,10 @@ Configuration
* `timezone`_
* `debug`_
* `default_path`_
* `exception_controller`_
* `form_themes`_
* `globals`_
* `number_format`_
* `decimals`_
@@ -62,6 +64,8 @@ If ``true``, whenever a template is rendered, Symfony checks first if its source
code has changed since it was compiled. If it has changed, the template is
compiled again automatically.
.. _config-twig-autoescape:
autoescape
~~~~~~~~~~
@@ -73,7 +77,7 @@ individually in the templates).
.. caution::
Setting this option to ``false`` is dangerous and it will make your
application vulnerable to XSS exploits because most third-party bundles
application vulnerable to `XSS attacks`_ because most third-party bundles
assume that auto-escaping is enabled and they don't escape contents
themselves.
@@ -139,8 +143,8 @@ charset
**type**: ``string`` **default**: ``'%kernel.charset%'``
The charset used by the template files. By default it's the same as the value of
the ``kernel.charset`` container parameter, which is ``UTF-8`` by default in
Symfony applications.
the :ref:`kernel.charset container parameter <configuration-kernel-charset>`,
which is ``UTF-8`` by default in Symfony applications.
date
~~~~
@@ -181,6 +185,17 @@ debug
If ``true``, the compiled templates include a ``__toString()`` method that can
be used to display their nodes.
.. _config-twig-default-path:
default_path
~~~~~~~~~~~~
**type**: ``string`` **default**: ``'%kernel.project_dir%/templates'``
The path to the directory where Symfony will look for the application Twig
templates by default. If you store the templates in more than one directory, use
the :ref:`paths <config-twig-paths>` option too.
.. _config-twig-exception-controller:
exception_controller
@@ -195,7 +210,8 @@ is what's responsible for rendering specific templates under different error
conditions (see :doc:`/controller/error_pages`). Modifying this
option is advanced. If you need to customize an error page you should use
the previous link. If you need to perform some behavior on an exception,
you should add a listener to the ``kernel.exception`` event (see :ref:`dic-tags-kernel-event-listener`).
you should add an :doc:`event listener </event_dispatcher>` to the
:ref:`kernel.exception event <kernel-kernel.exception>`.
.. _config-twig-form-themes:
@@ -253,6 +269,14 @@ These global themes are applied to all forms, even those which use the
:ref:`form_theme Twig tag <reference-twig-tag-form-theme>`, but you can
:ref:`disable global themes for specific forms <disabling-global-themes-for-single-forms>`.
globals
~~~~~~~
**type**: ``array`` **default**: ``[]``
It defines the global variables injected automatically into all Twig templates.
Learn more about :doc:`Twig global variables </templating/global_variables>`.
number_format
~~~~~~~~~~~~~
@@ -301,15 +325,6 @@ on. Set it to ``0`` to disable all the optimizations. You can even enable or
disable these optimizations selectively, as explained in the Twig documentation
about `the optimizer extension`_.
.. _config-twig-default-path:
default_path
~~~~~~~~~~~~
**type**: ``string`` **default**: ``'%kernel.project_dir%/templates'``
The default directory where Symfony will look for Twig templates.
.. _config-twig-paths:
paths
@@ -317,23 +332,8 @@ paths
**type**: ``array`` **default**: ``null``
.. deprecated:: 4.2
Using the ``src/Resources/views/`` directory to store templates was
deprecated in Symfony 4.2. Use instead the directory defined in the
``default_path`` option (which is ``templates/`` by default).
This option defines the directories where Symfony will look for Twig templates
in addition to the default locations. Symfony looks for the templates in the
following order:
#. The directories defined in this option;
#. The ``Resources/views/`` directories of the bundles used in the application;
#. The ``src/Resources/views/`` directory of the application;
#. The directory defined in the ``default_path`` option.
The values of the ``paths`` option are defined as ``key: value`` pairs where the
``value`` part can be ``null``. For example:
Defines the directories where application templates are stored in addition to
the directory defined in the :ref:`default_path option <config-twig-default-path>`:
.. configuration-block::
@@ -343,7 +343,8 @@ The values of the ``paths`` option are defined as ``key: value`` pairs where the
twig:
# ...
paths:
'%kernel.project_dir%/vendor/acme/foo-bar/templates': ~
'email/default/templates': ~
'backend/templates': 'admin'
.. code-block:: xml
@@ -357,7 +358,8 @@ The values of the ``paths`` option are defined as ``key: value`` pairs where the
<twig:config>
<!-- ... -->
<twig:path>%kernel.project_dir%/vendor/acme/foo-bar/templates</twig:path>
<twig:path>email/default/templates</twig:path>
<twig:path namespace="admin">backend/templates</twig:path>
</twig:config>
</container>
@@ -367,60 +369,12 @@ The values of the ``paths`` option are defined as ``key: value`` pairs where the
$container->loadFromExtension('twig', [
// ...
'paths' => [
'%kernel.project_dir%/vendor/acme/foo-bar/templates' => null,
'email/default/templates' => null,
'backend/templates' => 'admin',
],
]);
The directories defined in the ``paths`` option have more priority than the
default directories defined by Symfony. In the above example, if the template
exists in the ``acme/foo-bar/templates/`` directory inside your application's
``vendor/``, it will be used by Symfony.
If you provide a value for any path, Symfony will consider it the Twig namespace
for that directory:
.. configuration-block::
.. code-block:: yaml
# config/packages/twig.yaml
twig:
# ...
paths:
'%kernel.project_dir%/vendor/acme/foo-bar/templates': 'foo_bar'
.. code-block:: xml
<!-- config/packages/twig.xml -->
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:twig="http://symfony.com/schema/dic/twig"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/twig https://symfony.com/schema/dic/twig/twig-1.0.xsd">
<twig:config>
<!-- ... -->
<twig:path namespace="foo_bar">%kernel.project_dir%/vendor/acme/foo-bar/templates</twig:path>
</twig:config>
</container>
.. code-block:: php
# config/packages/twig.php
$container->loadFromExtension('twig', [
// ...
'paths' => [
'%kernel.project_dir%/vendor/acme/foo-bar/templates' => 'foo_bar',
],
]);
This option is useful to not mess with the default template directories defined
by Symfony. Besides, it simplifies how you refer to those templates:
.. code-block:: text
@foo_bar/template_name.html.twig
Read more about :ref:`template directories and namespaces <templates-namespaces>`.
strict_variables
~~~~~~~~~~~~~~~~
@@ -432,3 +386,4 @@ attribute or method doesn't exist. If set to ``false`` these errors are ignored
and the non-existing values are replaced by ``null``.
.. _`the optimizer extension`: https://twig.symfony.com/doc/2.x/api.html#optimizer-extension
.. _`XSS attacks`: https://en.wikipedia.org/wiki/Cross-site_scripting

View File

@@ -1,38 +1,19 @@
.. index::
single: Symfony Twig extensions
.. _symfony2-twig-extensions:
Twig Extensions Defined by Symfony
==================================
Symfony Twig Extensions
=======================
Twig is the default template engine for Symfony. By itself, it already contains
a lot of built-in functions, filters, tags and tests. You can learn more about
them from the `Twig Reference`_.
The Symfony framework adds quite a few extra :ref:`functions <reference-twig-functions>`,
:ref:`filters <reference-twig-filters>`, :ref:`tags <reference-twig-tags>`
and :ref:`tests <reference-twig-tests>` to seamlessly integrate the
various Symfony components with Twig templates. The following sections
describe these extra features.
:ref:`Twig <twig-language>` is the template engine used in Symfony applications.
There are tens of `default filters and functions defined by Twig`_, but Symfony
also defines some filters, functions and tags to integrate the various Symfony
components with Twig templates. This article explains them all.
.. tip::
Technically, most of the extensions live in the `Twig Bridge`_. That code
might give you some ideas when you need to write your own Twig extension
as described in :doc:`/templating/twig_extension`.
.. note::
This reference only covers the Twig extensions provided by the Symfony
framework. You are probably using some other bundles as well, and
those might come with their own extensions not covered here.
.. tip::
The `Twig Extensions repository`_ contains some additional Twig extensions
that do not belong to the Twig core, so you might want to have a look at
the `Twig Extensions documentation`_.
If these extensions provided by Symfony are not enough, you can
:doc:`create a custom Twig extension </templating/twig_extension>` to define
even more filters and functions.
.. _reference-twig-functions:
@@ -54,20 +35,8 @@ render
**type**: ``array`` **default**: ``[]``
Makes a request to the given internal URI or controller and returns the result.
It's commonly used to :doc:`embed controllers in templates </templating/embedding_controllers>`.
.. code-block:: twig
{# if the controller is associated with a route, use the path() or
url() functions to generate the URI used by render() #}
{{ render(path('latest_articles', {num: 5})) }}
{{ render(url('latest_articles', {num: 5})) }}
{# if you don't want to expose the controller with a public URL, use
the controller() function to define the controller to be executed #}
{{ render(controller('App\\Controller\\DefaultController::latestArticles', {num: 5})) }}
The render strategy can be specified in the ``strategy`` key of the options.
It's commonly used to :ref:`embed controllers in templates <templates-embed-controllers>`.
.. _reference-twig-function-render-esi:
@@ -112,6 +81,8 @@ Returns an instance of ``ControllerReference`` to be used with functions
like :ref:`render() <reference-twig-function-render>` and
:ref:`render_esi() <reference-twig-function-render-esi>`.
.. _reference-twig-function-asset:
asset
~~~~~
@@ -124,12 +95,18 @@ asset
``packageName`` *(optional)*
**type**: ``string`` | ``null`` **default**: ``null``
Returns a public path to ``path``, which takes into account the base path
set for the package and the URL path. More information in
:ref:`templating-assets`. Symfony provides various cache busting
implementations via the :ref:`reference-framework-assets-version`,
:ref:`reference-assets-version-strategy`, and
:ref:`reference-assets-json-manifest-path` configuration options.
Returns the public path of the given asset path (which can be a CSS file, a
JavaScript file, an image path, etc.). This function takes into account where
the application is installed (e.g. in case the project is accessed in a host
subirectory) and the optional asset package base path.
Symfony provides various cache busting implementations via the
:ref:`reference-framework-assets-version`, :ref:`reference-assets-version-strategy`,
and :ref:`reference-assets-json-manifest-path` configuration options.
.. seealso::
Read more about :ref:`linking to web assets from templates <templates-link-to-assets>`.
asset_version
~~~~~~~~~~~~~~
@@ -142,7 +119,7 @@ asset_version
**type**: ``string`` | ``null`` **default**: ``null``
Returns the current version of the package, more information in
:ref:`templating-assets`.
:ref:`templates-link-to-assets`.
.. _reference-twig-function-csrf-token:
@@ -211,7 +188,7 @@ path
.. code-block:: twig
{{ path(name, parameters = [], relative = false) }}
{{ path(route_name, route_parameters = [], relative = false) }}
``name``
**type**: ``string``
@@ -221,19 +198,19 @@ path
**type**: ``boolean`` **default**: ``false``
Returns the relative URL (without the scheme and host) for the given route.
If ``relative`` is enabled, it'll create a path relative to the current
path. More information in :ref:`templating-pages`.
If ``relative`` is enabled, it'll create a path relative to the current path.
.. seealso::
Read :doc:`/routing` to learn more about the Routing component.
Read more about :doc:`Symfony routing </routing>` and about
:ref:`creating links in Twig templates <templates-link-to-pages>`.
url
~~~
.. code-block:: twig
{{ url(name, parameters = [], schemeRelative = false) }}
{{ url(route_name, route_parameters = [], schemeRelative = false) }}
``name``
**type**: ``string``
@@ -243,12 +220,12 @@ url
**type**: ``boolean`` **default**: ``false``
Returns the absolute URL (with scheme and host) for the given route. If
``schemeRelative`` is enabled, it'll create a scheme-relative URL. More
information in :ref:`templating-pages`.
``schemeRelative`` is enabled, it'll create a scheme-relative URL.
.. seealso::
Read :doc:`/routing` to learn more about the Routing component.
Read more about :doc:`Symfony routing </routing>` and about
:ref:`creating links in Twig templates <templates-link-to-pages>`.
absolute_url
~~~~~~~~~~~~
@@ -260,17 +237,9 @@ absolute_url
``path``
**type**: ``string``
Returns the absolute URL from the passed relative path. For example, assume
you're on the following page in your app:
``http://example.com/products/hover-board``.
.. code-block:: twig
{{ absolute_url('/human.txt') }}
{# http://example.com/human.txt #}
{{ absolute_url('products_icon.png') }}
{# http://example.com/products/products_icon.png #}
Returns the absolute URL from the passed relative path. Combine it with the
:ref:`asset() function <reference-twig-function-asset>` to generate absolute URLs
for web assets. Read more about :ref:`Linking to CSS, JavaScript and Image Assets <templates-link-to-assets>`.
relative_path
~~~~~~~~~~~~~
@@ -297,8 +266,8 @@ you're on the following page in your app:
expression
~~~~~~~~~~
Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` in
Twig.
Creates an :class:`Symfony\\Component\\ExpressionLanguage\\Expression` related
to the :doc:`ExpressionLanguage component </components/expression_language>`.
Form Related Functions
~~~~~~~~~~~~~~~~~~~~~~
@@ -652,27 +621,11 @@ in the article about :doc:`customizing form rendering </form/form_customization>
Global Variables
----------------
.. _reference-twig-global-app:
app
~~~
The ``app`` variable is available everywhere and gives access to many commonly
needed objects and values. It is an instance of
:class:`Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables`.
The ``app`` variable is injected automatically by Symfony in all templates and
provides access to lots of useful application information. Read more about the
:ref:`Twig global app variable <twig-app-variable>`.
The available attributes are:
* ``app.user``, a PHP object representing the current user;
* ``app.request``, a :class:`Symfony\\Component\\HttpFoundation\\Request` object;
* ``app.session``, a :class:`Symfony\\Component\\HttpFoundation\\Session\\Session` object;
* ``app.environment``, a string with the name of the execution environment;
* ``app.debug``, a boolean telling whether the debug mode is enabled in the app;
* ``app.token``, a :class:`Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface`
object representing the security token
* ``app.flashes``, returns flash messages from the session
.. _`Twig Reference`: https://twig.symfony.com/doc/2.x/#reference
.. _`Twig Extensions repository`: https://github.com/twigphp/Twig-extensions
.. _`Twig Extensions documentation`: http://twig-extensions.readthedocs.io/en/latest/
.. _`Twig Bridge`: https://github.com/symfony/symfony/tree/master/src/Symfony/Bridge/Twig/Extension
.. _`default filters and functions defined by Twig`: https://twig.symfony.com/doc/2.x/#reference

View File

@@ -1238,8 +1238,8 @@ information in a controller via the ``Request`` object::
You can get this information in services too injecting the ``request_stack``
service to :doc:`get the Request object in a service </service_container/request>`.
In Twig templates, use the :ref:`global app object <reference-twig-global-app>`
to get the request and its attributes:
In templates, use the :ref:`Twig global app variable <twig-app-variable>` to get
the request and its attributes:
.. code-block:: twig
@@ -1256,67 +1256,14 @@ Symfony defines some special controllers to render templates and redirect to
other routes from the route configuration so you don't have to create a
controller action.
Rendering Templates
~~~~~~~~~~~~~~~~~~~
Rendering a Template Directly from a Route
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Use the ``TemplateController`` to render the template whose path is defined in
the ``template`` option:
Read the section about :ref:`rendering a template from a route <templates-render-from-route>`
in the main article about Symfony templates.
.. configuration-block::
.. code-block:: yaml
# config/routes.yaml
about_us:
path: /site/about-us
controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction
defaults:
template: 'static_pages/about_us.html.twig'
# optionally you can define some arguments passed to the template
site_name: 'ACME'
theme: 'dark'
.. code-block:: xml
<!-- config/routes.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
https://symfony.com/schema/routing/routing-1.0.xsd">
<route id="about_us" path="/site/about-us"
controller="Symfony\Bundle\FrameworkBundle\Controller\TemplateController::templateAction">
<default key="template">static_pages/about_us.html.twig</default>
<!-- optionally you can define some arguments passed to the template -->
<default key="site_name">ACME</default>
<default key="theme">dark</default>
</route>
</routes>
.. code-block:: php
// config/routes.php
use App\Controller\DefaultController;
use Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$routes->add('about_us', '/site/about-us')
->controller([TemplateController::class, 'templateAction'])
->defaults([
'template' => 'static_pages/about_us.html.twig',
// optionally you can define some arguments passed to the template
'site_name' => 'ACME',
'theme' => 'dark',
])
;
};
Redirecting to URLs and Routes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Redirecting to URLs and Routes Directly from a Route
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Use the ``RedirectController`` to redirect to other routes (``redirectAction``)
and URLs (``urlRedirectAction``):
@@ -1901,28 +1848,8 @@ the :class:`Symfony\\Component\\Routing\\Generator\\UrlGeneratorInterface` class
Generating URLs in Templates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Twig template language used in :doc:`Symfony templates </templating>`
provides some functions to generate both relative and absolute URLs:
.. code-block:: html+twig
{# generates relative URLs #}
<a href="{{ path('sign_up') }}">Sign up</a>
<a href="{{ path('user_profile', {username: app.user.username}) }}">
View your profile
</a>
<a href="{{ path('user_profile', {username: app.user.username, _locale: 'es'}) }}">
Ver mi perfil
</a>
{# generates absolute URLs #}
<a href="{{ url('sign_up') }}">Sign up</a>
<a href="{{ url('user_profile', {username: app.user.username}) }}">
View your profile
</a>
<a href="{{ url('user_profile', {username: app.user.username, _locale: 'es'}) }}">
Ver mi perfil
</a>
Read the section about :ref:`creating links between pages <templates-link-to-pages>`
in the main article about Symfony templates.
Generating URLs in JavaScript
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -723,8 +723,8 @@ If you need to get the logged in user from a service, use the
Fetch the User in a Template
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In a Twig Template the user object can be accessed via the :ref:`app.user <reference-twig-global-app>`
key:
In a Twig Template the user object is available via the ``app.user`` variable
thanks to the :ref:`Twig global app variable <twig-app-variable>`:
.. code-block:: html+twig

1100
templates.rst Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,820 +0,0 @@
.. index::
single: Templating
Creating and Using Templates
============================
As explained in :doc:`the previous article </controller>`, controllers are
responsible for handling each request that comes into a Symfony application and
they usually end up rendering a template to generate the response contents.
In reality, the controller delegates most of the heavy work to other places so
that code can be tested and reused. When a controller needs to generate HTML,
CSS or any other content, it hands the work off to the templating engine.
In this article, you'll learn how to write powerful templates that can be
used to return content to the user, populate email bodies, and more. You'll
learn shortcuts, clever ways to extend templates and how to reuse template
code.
.. index::
single: Templating; What is a template?
Templates
---------
A template is a text file that can generate any text-based format
(HTML, XML, CSV, LaTeX ...). The most familiar type of template is a *PHP*
template - a text file parsed by PHP that contains a mix of text and PHP code:
.. code-block:: html+php
<!DOCTYPE html>
<html>
<head>
<title>Welcome to Symfony!</title>
</head>
<body>
<h1><?= $page_title ?></h1>
<ul id="navigation">
<?php foreach ($navigation as $item): ?>
<li>
<a href="<?= $item->getHref() ?>">
<?= $item->getCaption() ?>
</a>
</li>
<?php endforeach ?>
</ul>
</body>
</html>
.. index:: Twig; Introduction
But Symfony packages an even more powerful templating language called `Twig`_.
Twig allows you to write concise, readable templates that are more friendly
to web designers and, in several ways, more powerful than PHP templates:
.. code-block:: html+twig
<!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>
Twig defines three types of special syntax:
``{{ ... }}``
"Says something": prints a variable or the result of an expression to the
template.
``{% ... %}``
"Does something": a **tag** that controls the logic of the template; it is
used to execute statements such as for-loops for example.
``{# ... #}``
"Comment something": it's the equivalent of the PHP ``/* comment */`` syntax.
It's used to add single or multi-line comments. The content of the comments
isn't included in the rendered pages.
Twig also contains **filters**, which modify content before being rendered.
The following makes the ``title`` variable all uppercase before rendering
it:
.. code-block:: twig
{{ title|upper }}
Twig comes with a long list of `tags`_, `filters`_ and `functions`_ that are available
by default. You can even add your own *custom* filters, functions (and more) via
a :doc:`Twig Extension </templating/twig_extension>`. Run the following command
to list them all:
.. code-block:: terminal
$ php bin/console debug:twig
Twig code will look similar to PHP code, with subtle, nice differences. The following
example uses a standard ``for`` tag and the ``cycle()`` function to print ten div tags,
with alternating ``odd``, ``even`` classes:
.. code-block:: html+twig
{% for i in 1..10 %}
<div class="{{ cycle(['even', 'odd'], i) }}">
<!-- some HTML here -->
</div>
{% endfor %}
Throughout this article, template examples will be shown in both Twig and PHP.
.. sidebar:: Why Twig?
Twig templates are meant to be simple and won't process PHP tags. This
is by design: the Twig template system is meant to express presentation,
not program logic. The more you use Twig, the more you'll appreciate
and benefit from this distinction. And you'll be loved by
web designers everywhere.
Twig can also do things that PHP can't, such as whitespace control,
sandboxing, automatic HTML escaping, manual contextual output escaping,
and the inclusion of custom functions and filters that only affect templates.
Twig contains a lot of features that make writing templates easier and more concise.
Take the following example, which combines a loop with a logical ``if``
statement:
.. code-block:: html+twig
<ul>
{% for user in users if user.active %}
<li>{{ user.username }}</li>
{% else %}
<li>No users found</li>
{% endfor %}
</ul>
.. index::
pair: Twig; Cache
Twig Template Caching
~~~~~~~~~~~~~~~~~~~~~
Twig is fast because each template is compiled to a native PHP class and cached.
But don't worry: this happens automatically and doesn't require *you* to do anything.
And while you're developing, Twig is smart enough to re-compile your templates after
you make any changes. That means Twig is fast in production, but convenient to use
while developing.
.. index::
single: Templating; Inheritance
.. _twig-inheritance:
Template Inheritance and Layouts
--------------------------------
More often than not, templates in a project share common elements, like the
header, footer, sidebar or more. In Symfony, this problem is thought about
differently: a template can be decorated by another one. This works
exactly the same as PHP classes: template inheritance allows you to build
a base "layout" template that contains all the common elements of your site
defined as **blocks** (think "PHP class with base methods"). A child template
can extend the base layout and override any of its blocks (think "PHP subclass
that overrides certain methods of its parent class").
First, build a base layout file:
.. code-block:: html+twig
{# templates/base.html.twig #}
<!DOCTYPE html>
<html>
<head>
<meta 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>
.. note::
Though the discussion about template inheritance will be in terms of Twig,
the philosophy is the same between Twig and PHP templates.
This template defines the base HTML skeleton document of a two-column
page. In this example, three ``{% block %}`` areas are defined (``title``,
``sidebar`` and ``body``). Each block may be overridden by a child template
or left with its default implementation. This template could also be rendered
directly. In that case the ``title``, ``sidebar`` and ``body`` blocks would
retain the default values used in this template.
A child template might look like this:
.. code-block:: html+twig
{# templates/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 %}
.. note::
The parent template is stored in ``templates/``, so its path is
``base.html.twig``. The template naming conventions are explained
fully in :ref:`template-naming-locations`.
The key to template inheritance is the ``{% extends %}`` tag. This tells
the templating engine to first evaluate the base template, which sets up
the layout and defines several blocks. The child template is then rendered,
at which point the ``title`` and ``body`` blocks of the parent are replaced
by those from the child. Depending on the value of ``blog_entries``, the
output might look like this:
.. code-block:: html
<!DOCTYPE html>
<html>
<head>
<meta 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>
Notice that since the child template didn't define a ``sidebar`` block, the
value from the parent template is used instead. Content within a ``{% block %}``
tag in a parent template is always used by default.
.. tip::
You can use as many levels of inheritance as you want! See :doc:`/templating/inheritance`
for more info.
When working with template inheritance, here are some tips to keep in mind:
* If you use ``{% extends %}`` in a template, it must be the first tag in
that template;
* The more ``{% block %}`` tags you have in your base templates, the better.
Remember, child templates don't have to define all parent blocks, so create
as many blocks in your base templates as you want and give each a sensible
default. The more blocks your base templates have, the more flexible your
layout will be;
* If you find yourself duplicating content in a number of templates, it probably
means you should move that content to a ``{% block %}`` in a parent template.
In some cases, a better solution may be to move the content to a new template
and ``include`` it (see :ref:`including-templates`);
* If you need to get the content of a block from the parent template, you
can use the ``{{ parent() }}`` function. This is useful if you want to add
to the contents of a parent block instead of completely overriding it:
.. code-block:: html+twig
{% block sidebar %}
<h3>Table of Contents</h3>
{# ... #}
{{ parent() }}
{% endblock %}
.. index::
single: Templating; Naming conventions
single: Templating; File locations
.. _template-naming-locations:
Template Naming and Locations
-----------------------------
By default, templates can live in two different locations:
``templates/``
The application's ``views`` directory can contain application-wide base templates
(i.e. your application's layouts and templates of the application bundle) as
well as templates that :ref:`override third party bundle templates <override-templates>`.
``vendor/path/to/CoolBundle/Resources/views/``
Each third party bundle houses its templates in its ``Resources/views/``
directory (and subdirectories). When you plan to share your bundle, you should
put the templates in the bundle instead of the ``templates/`` directory.
Most of the templates you'll use live in the ``templates/``
directory. The path you'll use will be relative to this directory. For example,
to render/extend ``templates/base.html.twig``, you'll use the
``base.html.twig`` path and to render/extend
``templates/blog/index.html.twig``, you'll use the
``blog/index.html.twig`` path.
.. _template-referencing-in-bundle:
Referencing Templates in a Bundle
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*If* you need to refer to a template that lives in a bundle, Symfony uses the
Twig namespaced syntax (``@BundleName/directory/filename.html.twig``). This allows
for several types of templates, each which lives in a specific location:
* ``@AcmeBlog/Blog/index.html.twig``: This syntax is used to specify a
template for a specific page. The three parts of the string, each separated
by a slash (``/``), mean the following:
* ``@AcmeBlog``: is the bundle name without the ``Bundle`` suffix. This template
lives in the AcmeBlogBundle (e.g. ``src/Acme/BlogBundle``);
* ``Blog``: (*directory*) indicates that the template lives inside the
``Blog`` subdirectory of ``Resources/views/``;
* ``index.html.twig``: (*filename*) the actual name of the file is
``index.html.twig``.
Assuming that the AcmeBlogBundle lives at ``src/Acme/BlogBundle``, the
final path to the layout would be ``src/Acme/BlogBundle/Resources/views/Blog/index.html.twig``.
* ``@AcmeBlog/layout.html.twig``: This syntax refers to a base template
that's specific to the AcmeBlogBundle. Since the middle, "directory", portion
is missing (e.g. ``Blog``), the template lives at
``Resources/views/layout.html.twig`` inside AcmeBlogBundle.
Using this namespaced syntax instead of the real file paths allows applications
to :ref:`override templates that live inside any bundle <override-templates>`.
Template Suffix
~~~~~~~~~~~~~~~
Every template name also has two extensions that specify the *format* and
*engine* for that template.
======================== ====== ======
Filename Format Engine
======================== ====== ======
``blog/index.html.twig`` HTML Twig
``blog/index.html.php`` HTML PHP
``blog/index.css.twig`` CSS Twig
======================== ====== ======
By default, any Symfony template can be written in either Twig or PHP, and
the last part of the extension (e.g. ``.twig`` or ``.php``) specifies which
of these two *engines* should be used. The first part of the extension,
(e.g. ``.html``, ``.css``, etc) is the final format that the template will
generate. Unlike the engine, which determines how Symfony parses the template,
this is an organizational tactic used in case the same resource needs to be
rendered as HTML (``index.html.twig``), XML (``index.xml.twig``), or any other
format. For more information, read the :doc:`/templating/formats` section.
.. index::
single: Templating; Tags and helpers
single: Templating; Helpers
Tags and Helpers
----------------
You already understand the basics of templates, how they're named and how
to use template inheritance. The hardest parts are already behind you. In
this section, you'll learn about a large group of tools available to help
perform the most common template tasks such as including other templates,
linking to pages and including images.
Symfony comes bundled with several specialized Twig tags and functions that
ease the work of the template designer. In PHP, the templating system provides
an extensible *helper* system that provides useful features in a template
context.
You've already seen a few built-in Twig tags like ``{% block %}`` and
``{% extends %}``. Here you will learn a few more.
.. index::
single: Templating; Including other templates
.. _including-templates:
.. _including-other-templates:
Including other Templates
~~~~~~~~~~~~~~~~~~~~~~~~~
You'll often want to include the same template or code fragment on several
pages. For example, in an application with "news articles", the
template code displaying an article might be used on the article detail page,
on a page displaying the most popular articles, or in a list of the latest
articles.
When you need to reuse a chunk of PHP code, you typically move the code to
a new PHP class or function. The same is true for templates. By moving the
reused template code into its own template, it can be included from any other
template. First, create the template that you'll need to reuse.
.. code-block:: html+twig
{# templates/article/article_details.html.twig #}
<h2>{{ article.title }}</h2>
<h3 class="byline">by {{ article.authorName }}</h3>
<p>
{{ article.body }}
</p>
Including this template from any other template is achieved with the
``{{ include() }}`` function:
.. code-block:: html+twig
{# templates/article/list.html.twig #}
{% extends 'layout.html.twig' %}
{% block body %}
<h1>Recent Articles<h1>
{% for article in articles %}
{{ include('article/article_details.html.twig', { 'article': article }) }}
{% endfor %}
{% endblock %}
Notice that the template name follows the same typical convention. The
``article_details.html.twig`` template uses an ``article`` variable, which we
pass to it. In this case, you could avoid doing this entirely, as all of the
variables available in ``list.html.twig`` are also available in
``article_details.html.twig`` (unless you set `with_context`_ to false).
.. tip::
The ``{'article': article}`` syntax is the standard Twig syntax for hash
maps (i.e. an array with named keys). If you needed to pass in multiple
elements, it would look like this: ``{'foo': foo, 'bar': bar}``.
.. index::
single: Templating; Linking to pages
.. _templating-pages:
Linking to Pages
~~~~~~~~~~~~~~~~
Creating links to other pages in your application is one of the most common
jobs for a template. Instead of hardcoding URLs in templates, use the ``path``
Twig function (or the ``router`` helper in PHP) to generate URLs based on
the routing configuration. Later, if you want to modify the URL of a particular
page, all you'll need to do is change the routing configuration: the templates
will automatically generate the new URL.
First, link to the "welcome" page, which is accessible via the following routing
configuration:
.. configuration-block::
.. code-block:: php-annotations
// src/Controller/WelcomeController.php
// ...
use Symfony\Component\Routing\Annotation\Route;
class WelcomeController extends AbstractController
{
/**
* @Route("/", name="welcome", methods={"GET"})
*/
public function index()
{
// ...
}
}
.. code-block:: yaml
# config/routes.yaml
welcome:
path: /
controller: App\Controller\WelcomeController::index
methods: GET
.. code-block:: xml
<!-- config/routes.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
https://symfony.com/schema/routing/routing-1.0.xsd">
<route id="welcome" path="/" controller="App\Controller\WelcomeController::index" methods="GET"/>
</routes>
.. code-block:: php
// config/routes.php
use App\Controller\WelcomeController;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$routes->add('welcome', '/')
->controller([WelcomeController::class, 'index'])
->methods(['GET'])
;
};
To link to the page, use the ``path()`` Twig function and refer to the route:
.. code-block:: html+twig
<a href="{{ path('welcome') }}">Home</a>
As expected, this will generate the URL ``/``. Now, for a more complicated
route:
.. configuration-block::
.. code-block:: php-annotations
// src/Controller/ArticleController.php
// ...
use Symfony\Component\Routing\Annotation\Route;
class ArticleController extends AbstractController
{
/**
* @Route("/article/{slug}", name="article_show", methods={"GET"})
*/
public function show($slug)
{
// ...
}
}
.. code-block:: yaml
# config/routes.yaml
article_show:
path: /article/{slug}
controller: App\Controller\ArticleController::show
methods: GET
.. code-block:: xml
<!-- config/routes.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing
https://symfony.com/schema/routing/routing-1.0.xsd">
<route id="article_show"
path="/article/{slug}"
controller="App\Controller\ArticleController::show"
methods="GET"/>
</routes>
.. code-block:: php
// config/routes.php
use App\Controller\ArticleController;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$routes->add('article_show', '/articles/{slug}')
->controller([ArticleController::class, 'show'])
->methods(['GET'])
;
};
In this case, you need to specify both the route name (``article_show``) and
a value for the ``{slug}`` parameter. Using this route, revisit the
``recent_list.html.twig`` template from the previous section and link to the articles
correctly:
.. code-block:: html+twig
{# templates/article/recent_list.html.twig #}
{% for article in articles %}
<a href="{{ path('article_show', {'slug': article.slug}) }}">
{{ article.title }}
</a>
{% endfor %}
.. tip::
You can also generate an absolute URL by using the ``url()`` Twig function:
.. code-block:: html+twig
<a href="{{ url('welcome') }}">Home</a>
.. index::
single: Templating; Linking to assets
.. _templating-assets:
Linking to Assets
~~~~~~~~~~~~~~~~~
Templates also commonly refer to images, JavaScript, stylesheets and other
assets. You could hard-code the web path to these assets (e.g. ``/images/logo.png``),
but Symfony provides a more dynamic option via the ``asset()`` Twig function.
To use this function, install the *asset* package:
.. code-block:: terminal
$ composer require symfony/asset
You can now use the ``asset()`` function:
.. code-block:: html+twig
<img src="{{ asset('images/logo.png') }}" alt="Symfony!"/>
<link href="{{ asset('css/blog.css') }}" rel="stylesheet"/>
The ``asset()`` function's main purpose is to make your application more portable.
If your application lives at the root of your host (e.g. ``http://example.com``),
then the rendered paths should be ``/images/logo.png``. But if your application
lives in a subdirectory (e.g. ``http://example.com/my_app``), each asset path
should render with the subdirectory (e.g. ``/my_app/images/logo.png``). The
``asset()`` function takes care of this by determining how your application is
being used and generating the correct paths accordingly.
.. tip::
The ``asset()`` function supports various cache busting techniques via the
:ref:`version <reference-framework-assets-version>`,
:ref:`version_format <reference-assets-version-format>`, and
:ref:`json_manifest_path <reference-assets-json-manifest-path>` configuration options.
If you need absolute URLs for assets, use the ``absolute_url()`` Twig function
as follows:
.. code-block:: html+twig
<img src="{{ absolute_url(asset('images/logo.png')) }}" alt="Symfony!"/>
.. index::
single: Templating; Including stylesheets and JavaScripts
single: Stylesheets; Including stylesheets
single: JavaScript; Including JavaScripts
Including Stylesheets and JavaScripts in Twig
---------------------------------------------
No site would be complete without including JavaScript files and stylesheets.
In Symfony, the inclusion of these assets is handled elegantly by taking
advantage of Symfony's template inheritance.
.. tip::
This section will teach you the philosophy behind including stylesheet
and JavaScript assets in Symfony. If you are interested in compiling and
creating those assets, check out the :doc:`Webpack Encore documentation </frontend>`
a tool that seamlessly integrates Webpack and other modern JavaScript tools
into Symfony applications.
Start by adding two blocks to your base template that will hold your assets:
one called ``stylesheets`` inside the ``head`` tag and another called ``javascripts``
just above the closing ``body`` tag. These blocks will contain all of the
stylesheets and JavaScripts that you'll need throughout your site:
.. code-block:: html+twig
{# templates/base.html.twig #}
<html>
<head>
{# ... #}
{% block stylesheets %}
<link href="{{ asset('css/main.css') }}" rel="stylesheet"/>
{% endblock %}
</head>
<body>
{# ... #}
{% block javascripts %}
<script src="{{ asset('js/main.js') }}"></script>
{% endblock %}
</body>
</html>
This looks almost like regular HTML, but with the addition of the
``{% block %}``. Those are useful when you need to include an extra stylesheet
or JavaScript from a child template. For example, suppose you have a contact
page and you need to include a ``contact.css`` stylesheet *just* on that
page. From inside that contact page's template, do the following:
.. code-block:: html+twig
{# templates/contact/contact.html.twig #}
{% extends 'base.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link href="{{ asset('css/contact.css') }}" rel="stylesheet"/>
{% endblock %}
{# ... #}
In the child template, you override the ``stylesheets`` block and put your new
stylesheet tag inside of that block. Since you want to add to the parent
block's content (and not actually *replace* it), you also use the ``parent()``
Twig function to include everything from the ``stylesheets`` block of the base
template.
You can also include assets located in your bundles' ``Resources/public/`` folder.
You will need to run the ``php bin/console assets:install target [--symlink]``
command, which copies (or symlinks) files into the correct location. (By default,
the target is the ``public/`` directory of your application.)
.. code-block:: html+twig
<link href="{{ asset('bundles/acmedemo/css/contact.css') }}" rel="stylesheet"/>
The end result is a page that includes ``main.js`` and both the ``main.css`` and ``contact.css``
stylesheets.
Referencing the Request, User or Session
----------------------------------------
Symfony also gives you a global ``app`` variable in Twig that can be used to access
the current user, the Request and more.
See :doc:`/templating/app_variable` for details.
Output Escaping
---------------
Twig performs automatic "output escaping" when rendering any content in order to
protect you from Cross Site Scripting (XSS) attacks.
Suppose ``description`` equals ``I <3 this product``:
.. code-block:: twig
{# output escaping is on automatically #}
{{ description }} {# I &lt;3 this product #}
{# disable output escaping with the raw filter #}
{{ description|raw }} {# I <3 this product #}
.. caution::
PHP templates do not automatically escape content.
For more details, see :doc:`/templating/escaping`.
Final Thoughts
--------------
The templating system is just *one* of the many tools in Symfony. And its job is
simple: allow us to render dynamic & complex HTML output so that this can ultimately
be returned to the user, sent in an email or something else.
Keep Going!
-----------
Before diving into the rest of Symfony, check out the :doc:`configuration system </configuration>`.
Learn more
----------
.. toctree::
:hidden:
configuration
.. toctree::
:maxdepth: 1
:glob:
/templating/*
.. _`Twig`: https://twig.symfony.com
.. _`tags`: https://twig.symfony.com/doc/2.x/tags/index.html
.. _`filters`: https://twig.symfony.com/doc/2.x/filters/index.html
.. _`functions`: https://twig.symfony.com/doc/2.x/functions/index.html
.. _`with_context`: https://twig.symfony.com/doc/2.x/functions/include.html

View File

@@ -6,9 +6,8 @@ How to Use PHP instead of Twig for Templates
.. deprecated:: 4.3
The integration of the Templating component in FrameworkBundle has been
deprecated since version 4.3 and will be removed in 5.0. PHP templates will
no longer be supported and you'll need to use Twig instead.
PHP templates have been deprecated in Symfony 4.3 and they will no longer be
supported in Symfony 5.0. Use :ref:`Twig templates <twig-language>` instead.
Symfony defaults to Twig for its template engine, but you can still use
plain PHP code if you want. Both templating engines are supported equally in
@@ -23,19 +22,18 @@ templates with PHP more powerful.
Rendering PHP Templates
-----------------------
.. deprecated:: 4.3
The integration of the Templating component in FrameworkBundle has been
deprecated since version 4.3 and will be removed in 5.0. PHP templates will
no longer be supported and you'll need to use Twig instead.
If you want to use the PHP templating engine, first install the templating component:
.. code-block:: terminal
$ composer require symfony/templating
Next, enable the php engine:
.. deprecated:: 4.3
The integration of the Templating component in FrameworkBundle has been
deprecated since version 4.3 and will be removed in 5.0.
Next, enable the PHP engine:
.. configuration-block::

View File

@@ -1,41 +0,0 @@
.. index::
single: Templating; app Variable
How to Access the User, Request, Session & more in Twig via the ``app`` Variable
================================================================================
During each request, Symfony will set a global template variable ``app``
in both Twig and PHP template engines by default. The ``app`` variable
is a :class:`Symfony\\Bridge\\Twig\\AppVariable`
instance which will give you access to some application specific variables
automatically:
``app.user``
The representation of the current user or ``null`` if there is none. The
value stored in this variable can be a :class:`Symfony\\Component\\Security\\Core\\User\\UserInterface`
object, any other object which implements a ``__toString()`` method or even
a regular string.
``app.request``
The :class:`Symfony\\Component\\HttpFoundation\\Request` object that represents
the current request (depending on your application, this can be a sub-request
or a regular request, as explained later).
``app.session``
The :class:`Symfony\\Component\\HttpFoundation\\Session\\Session` object that
represents the current user's session or ``null`` if there is none.
``app.environment``
The name of the current environment (``dev``, ``prod``, etc).
``app.debug``
True if in debug mode. False otherwise.
.. code-block:: html+twig
<p>Username: {{ app.user.username }}</p>
{% if app.debug %}
<p>Request method: {{ app.request.method }}</p>
<p>Application Environment: {{ app.environment }}</p>
{% endif %}
.. tip::
You can add your own global template variables, see
:doc:`/templating/global_variables`.

View File

@@ -1,83 +0,0 @@
.. index::
single: Templating; Debug
single: Templating; Dump
single: Twig; Debug
single: Twig; Dump
How to Dump Debug Information in Twig Templates
===============================================
When using PHP templates, you can use the
:ref:`dump() function from the VarDumper component <components-var-dumper-dump>`
if you need to quickly find the value of a variable passed. First, make sure it
is installed:
.. code-block:: terminal
$ composer require symfony/var-dumper
This is useful, for example, inside your controller::
// src/Controller/ArticleController.php
namespace App\Controller;
// ...
class ArticleController extends AbstractController
{
public function recentList()
{
$articles = ...;
dump($articles);
// ...
}
}
.. note::
The output of the ``dump()`` function is then rendered in the web developer
toolbar.
In a Twig template, you can use the ``dump`` utility as a function or a tag:
* ``{% dump foo.bar %}`` is the way to go when the original template output
shall not be modified: variables are not dumped inline, but in the web
debug toolbar;
* on the contrary, ``{{ dump(foo.bar) }}`` dumps inline and thus may or not
be suited to your use case (e.g. you shouldn't use it in an HTML
attribute or a ``<script>`` tag).
.. code-block:: html+twig
{# templates/article/recent_list.html.twig #}
{# the contents of this variable are sent to the Web Debug Toolbar #}
{% dump articles %}
{% for article in articles %}
{# the contents of this variable are displayed on the web page #}
{{ dump(article) }}
<a href="/article/{{ article.slug }}">
{{ article.title }}
</a>
{% endfor %}
By design, the ``dump()`` function is only available in the ``dev`` and ``test``
environments, to avoid leaking sensitive information in production. In fact,
trying to use the ``dump()`` function in the ``prod`` environment will result in
a PHP error.
Execute this command to list all Twig functions, filters, globals, tests and
registered namespaces and their paths:
.. code-block:: terminal
# list general information
$ php bin/console debug:twig
# filter output by any keyword
$ php bin/console debug:twig --filter=date
# pass a template name to show the physical file which will be loaded
$ php bin/console debug:twig @Twig/Exception/error.html.twig

View File

@@ -1,74 +0,0 @@
.. index::
single: Templating; Embedding action
How to Embed Controllers in a Template
======================================
.. note::
Rendering embedded controllers is "heavier" than including a template or calling
a custom Twig function. Unless you're planning on :doc:`caching the fragment </http_cache/esi>`,
avoid embedding many controllers.
:ref:`Including template fragments <including-other-templates>` is useful to
reuse the same content on several pages. However, this technique is not the best
solution in some cases.
Consider a website that displays on its sidebar the most recently published
articles. This list of articles is dynamic and it's probably the result of a
database query. In other words, the controller of any page that displays that
sidebar must make the same database query and pass the list of articles to the
included template fragment.
The alternative solution proposed by Symfony is to create a controller that only
displays the list of recent articles and then call to that controller from any
template that needs to display that content.
First, create a controller that renders a certain number of recent articles::
// src/Controller/ArticleController.php
namespace App\Controller;
// ...
class ArticleController extends AbstractController
{
public function recentArticles($max = 3)
{
// make a database call or other logic
// to get the "$max" most recent articles
$articles = ...;
return $this->render(
'article/recent_list.html.twig',
['articles' => $articles]
);
}
}
Then, create a ``recent_list`` template fragment to list the articles given by
the controller:
.. code-block:: html+twig
{# templates/article/recent_list.html.twig #}
{% for article in articles %}
<a href="{{ path('article_show', {slug: article.slug}) }}">
{{ article.title }}
</a>
{% endfor %}
Finally, call the controller from any template using the ``render()`` function
and the standard string syntax for controllers (i.e. **controllerNamespace**::**action**):
.. code-block:: html+twig
{# templates/base.html.twig #}
{# ... #}
<div id="sidebar">
{{ render(controller(
'App\\Controller\\ArticleController::recentArticles',
{ 'max': 3 }
)) }}
</div>

View File

@@ -1,91 +0,0 @@
.. index::
single: Templating; Output escaping
How to Escape Output in Templates
=================================
When generating HTML from a template, there is always a risk that a template
variable may output unintended HTML or dangerous client-side code. The result
is that dynamic content could break the HTML of the resulting page or allow
a malicious user to perform a `Cross Site Scripting`_ (XSS) attack. Consider
this classic example:
.. code-block:: twig
Hello {{ name }}
Imagine the user enters the following code for their name:
.. code-block:: html
<script>alert('hello!')</script>
Without any output escaping, the resulting template will cause a JavaScript
alert box to pop up:
.. code-block:: html
Hello <script>alert('hello!')</script>
And while this seems harmless, if a user can get this far, that same user
should also be able to write JavaScript that performs malicious actions
inside the secure area of an unknowing, legitimate user.
The answer to the problem is output escaping. With output escaping on, the
same template will render harmlessly, and literally print the ``script``
tag to the screen:
.. code-block:: html
Hello &lt;script&gt;alert(&#39;hello!&#39;)&lt;/script&gt;
The Twig and PHP templating systems approach the problem in different ways.
If you're using Twig, output escaping is on by default and you're protected.
In PHP, output escaping is not automatic, meaning you'll need to manually
escape where necessary.
Output Escaping in Twig
-----------------------
If you're using Twig templates, then output escaping is on by default. This
means that you're protected out-of-the-box from the unintentional consequences
of user-submitted code. By default, the output escaping assumes that content
is being escaped for HTML output.
In some cases, you'll need to disable output escaping when you're rendering
a variable that is trusted and contains markup that should not be escaped.
Suppose that administrative users are able to write articles that contain
HTML code. By default, Twig will escape the article body.
To render it normally, add the ``raw`` filter:
.. code-block:: twig
{{ article.body|raw }}
You can also disable output escaping inside a ``{% block %}`` area or
for an entire template. For more information, see `Output Escaping`_ in
the Twig documentation.
Output Escaping in PHP
----------------------
Output escaping is not automatic when using PHP templates. This means that
unless you explicitly choose to escape a variable, you're not protected. To
use output escaping, use the special ``escape()`` view method:
.. code-block:: html+php
Hello <?= $view->escape($name) ?>
By default, the ``escape()`` method assumes that the variable is being rendered
within an HTML context (and thus the variable is escaped to be safe for HTML).
The second argument lets you change the context. For example, to output something
in a JavaScript string, use the ``js`` context:
.. code-block:: html+php
var myMsg = 'Hello <?= $view->escape($name, 'js') ?>';
.. _`Cross Site Scripting`: https://en.wikipedia.org/wiki/Cross-site_scripting
.. _`Output Escaping`: https://twig.symfony.com/doc/2.x/api.html#escaper-extension

View File

@@ -1,77 +0,0 @@
.. index::
single: Templating; Formats
How to Work with Different Output Formats in Templates
======================================================
Templates are a generic way to render content in *any* format. While in
most cases you'll use templates to render HTML content, a template can just
generate JavaScript, CSS, XML or any other format.
For example, the same "resource" is often rendered in several formats.
To render an article index page in XML, include the format in the
template name:
* *XML template name*: ``article/show.xml.twig``
* *XML template filename*: ``show.xml.twig``
In reality, this is nothing more than a naming convention and the template
isn't actually rendered differently based on its format.
In many cases, you may want to allow a single controller to render multiple
different formats based on the "request format". For that reason, a common
pattern is to do the following::
// ...
use Symfony\Component\Routing\Annotation\Route;
class ArticleController extends AbstractController
{
/**
* @Route("/{slug}")
*/
public function show(Request $request, $slug)
{
// retrieve the article based on $slug
$article = ...;
$format = $request->getRequestFormat();
return $this->render('article/show.'.$format.'.twig', [
'article' => $article,
]);
}
}
The ``getRequestFormat()`` on the ``Request`` object defaults to ``html``,
but can return any other format based on the format requested by the user.
The request format is most often managed by the routing, where a route can
be configured so that ``/about-us`` sets the request format to ``html`` while
``/about-us.xml`` sets the format to ``xml``. This can be achieved by using the
:ref:`special _format parameter <routing-format-parameter>` in your route definition::
/**
* @Route("/{slug}.{_format}", defaults={"_format"="html"}, requirements={"_format"="html|xml"}))
*/
public function show(Request $request, $slug)
{
// ...
}
Now, include the ``_format`` placeholder when generating a route for another
format:
.. code-block:: html+twig
<a href="{{ path('article_show', {'slug': 'about-us', '_format': 'xml'}) }}">
View as XML
</a>
.. tip::
When building APIs, using file name extensions often isn't the best
solution. The FOSRestBundle provides a request listener that uses content
negotiation. For more information, check out the bundle's `Request Format Listener`_
documentation.
.. _Request Format Listener: http://symfony.com/doc/current/bundles/FOSRestBundle/3-listener-support.html#format-listener

View File

@@ -1,11 +1,12 @@
.. index::
single: Templating; Global variables
How to Inject Variables into all Templates (i.e. global Variables)
==================================================================
How to Inject Variables Automatically into all Templates
========================================================
Sometimes you want a variable to be accessible to all the templates you use.
This is possible inside your ``config/packages/twig.yaml`` file:
Twig allows to inject automatically one or more variables into all templates.
These global variables are defined in the ``twig.globals`` option inside the
main Twig configuration file:
.. configuration-block::
@@ -15,7 +16,7 @@ This is possible inside your ``config/packages/twig.yaml`` file:
twig:
# ...
globals:
ga_tracking: UA-xxxxx-x
ga_tracking: 'UA-xxxxx-x'
.. code-block:: xml
@@ -45,78 +46,25 @@ This is possible inside your ``config/packages/twig.yaml`` file:
],
]);
Now, the variable ``ga_tracking`` is available in all Twig templates:
Now, the variable ``ga_tracking`` is available in all Twig templates, so you
can use it without having to pass it explicitly from the controller or service
that renders the template:
.. code-block:: html+twig
<p>The google tracking code is: {{ ga_tracking }}</p>
It's that easy!
Using Service Container Parameters
----------------------------------
You can also take advantage of the built-in :ref:`service-container-parameters`
system, which lets you isolate or reuse the value:
.. code-block:: yaml
# config/services.yaml
parameters:
ga_tracking: UA-xxxxx-x
.. configuration-block::
.. code-block:: yaml
# config/packages/twig.yaml
twig:
globals:
ga_tracking: '%ga_tracking%'
.. code-block:: xml
<!-- config/packages/twig.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:twig="http://symfony.com/schema/dic/twig"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/twig
https://symfony.com/schema/dic/twig/twig-1.0.xsd">
<twig:config>
<twig:global key="ga_tracking">%ga_tracking%</twig:global>
</twig:config>
</container>
.. code-block:: php
// config/packages/twig.php
$container->loadFromExtension('twig', [
'globals' => [
'ga_tracking' => '%ga_tracking%',
],
]);
The same variable is available exactly as before.
<p>The Google tracking code is: {{ ga_tracking }}</p>
Referencing Services
--------------------
Instead of using static values, you can also set the value to a service.
Whenever the global variable is accessed in the template, the service will be
requested from the service container and you get access to that object.
In addition to static values, Twig global variables can also reference services
from the :doc:`service container </service_container>`. The main drawback is
that these services are not loaded lazily. In other words, as soon as Twig is
loaded, your service is instantiated, even if you never use that global variable.
.. note::
The service is not loaded lazily. In other words, as soon as Twig is
loaded, your service is instantiated, even if you never use that global
variable.
To define a service as a global Twig variable, prefix the string with ``@``.
This should feel familiar, as it's the same syntax you use in service configuration.
To define a service as a global Twig variable, prefix the service ID string with
the ``@`` character, which is the usual syntax to
:ref:`refer to services in container parameters <service-container-parameters>`:
.. configuration-block::
@@ -127,7 +75,7 @@ This should feel familiar, as it's the same syntax you use in service configurat
# ...
globals:
# the value is the service's id
user_management: '@App\Service\UserManagement'
uuid: '@App\Generator\UuidGenerator'
.. code-block:: xml
@@ -143,7 +91,7 @@ This should feel familiar, as it's the same syntax you use in service configurat
<twig:config>
<!-- ... -->
<twig:global key="user_management">@App\Service\UserManagement</twig:global>
<twig:global key="uuid">@App\Generator\UuidGenerator</twig:global>
</twig:config>
</container>
@@ -153,6 +101,13 @@ This should feel familiar, as it's the same syntax you use in service configurat
$container->loadFromExtension('twig', [
// ...
'globals' => [
'user_management' => '@App\Service\UserManagement',
'uuid' => '@App\Generator\UuidGenerator',
],
]);
Now you can use the ``uuid`` variable in any Twig template to access to the
``UuidGenerator`` service:
.. code-block:: twig
UUID: {{ uuid.generate }}

View File

@@ -4,10 +4,18 @@
How to Embed Asynchronous Content with hinclude.js
==================================================
Controllers can be embedded asynchronously using the `hinclude.js`_ JavaScript library.
:ref:`Embedding controllers in templates <templates-embed-controllers>` is one
of the ways to reuse contents across multiple templates. To further improve
performance you can use the `hinclude.js`_ JavaScript library to embed
controllers asynchronously.
First, include the `hinclude.js`_ library in your page
ref:`linking to it <templates-link-to-assets>` from the template or adding it
to your application JavaScript :doc:`using Webpack Encore </frontend>`.
As the embedded content comes from another page (or controller for that matter),
Symfony uses a version of the standard ``render()`` function to configure ``hinclude``
tags:
Symfony uses a version of the standard ``render()`` function to configure
``hinclude`` tags in templates:
.. code-block:: twig
@@ -16,49 +24,11 @@ tags:
.. note::
hinclude.js_ needs to be included in your page to work.
When using the ``controller()`` function, you must also configure the
:ref:`fragments path option <fragments-path-config>`.
.. note::
When using a controller instead of a URL, you must enable the Symfony
``fragments`` configuration:
.. configuration-block::
.. code-block:: yaml
# config/packages/framework.yaml
framework:
# ...
fragments: { path: /_fragment }
.. code-block:: xml
<!-- config/packages/framework.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<!-- ... -->
<framework:config>
<framework:fragment path="/_fragment"/>
</framework:config>
</container>
.. code-block:: php
// config/packages/framework.php
$container->loadFromExtension('framework', [
// ...
'fragments' => ['path' => '/_fragment'],
]);
Default content (while loading or if JavaScript is disabled) can be set globally
in your application configuration:
When JavaScript is disabled or it takes a long time to load you can display a
default content rendering some template:
.. configuration-block::
@@ -109,13 +79,13 @@ any global default template that is defined):
.. code-block:: twig
{{ render_hinclude(controller('...'), {
'default': 'default/content.html.twig'
default: 'default/content.html.twig'
}) }}
Or you can also specify a string to display as the default content:
.. code-block:: twig
{{ render_hinclude(controller('...'), {'default': 'Loading...'}) }}
{{ render_hinclude(controller('...'), {default: 'Loading...'}) }}
.. _`hinclude.js`: http://mnot.github.io/hinclude/

View File

@@ -1,54 +0,0 @@
.. index::
single: Templating; Three-level inheritance pattern
How to Organize Your Twig Templates Using Inheritance
=====================================================
One common way to use inheritance is to use a three-level approach. This
method works perfectly with the three different types of templates that were just
covered:
* Create an ``templates/base.html.twig`` file that contains the main
layout for your application (like in the previous example). Internally, this
template is called ``base.html.twig``;
* Create a template for each "section" of your site. For example, the blog
functionality would have a template called ``blog/layout.html.twig`` that
contains only blog section-specific elements;
.. code-block:: html+twig
{# templates/blog/layout.html.twig #}
{% extends 'base.html.twig' %}
{% block body %}
<h1>Blog Application</h1>
{% block content %}{% endblock %}
{% endblock %}
* Create individual templates for each page and make each extend the appropriate
section template. For example, the "index" page would be called something
close to ``blog/index.html.twig`` and list the actual blog posts.
.. code-block:: html+twig
{# templates/blog/index.html.twig #}
{% extends 'blog/layout.html.twig' %}
{% block content %}
{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}
{% endblock %}
Notice that this template extends the section template (``blog/layout.html.twig``)
which in turn extends the base application layout (``base.html.twig``). This is
the common three-level inheritance model.
When building your application, you may choose to follow this method or
make each page template extend the base application template directly
(e.g. ``{% extends 'base.html.twig' %}``). The three-template model is a
best-practice method used by vendor bundles so that the base template for a
bundle can be overridden to properly extend your application's base layout.

View File

@@ -1,135 +0,0 @@
.. index::
single: Templating; Namespaced Twig Paths
How to Use and Register Namespaced Twig Paths
=============================================
Usually, when you refer to a template, you'll use the relative path from the
main ``templates/`` dir at the root of the project:
.. code-block:: twig
{# this template is located in templates/layout.html.twig #}
{% extends "layout.html.twig" %}
{# this template is located in templates/user/profile.html.twig #}
{{ include('user/profile.html.twig') }}
If the application defines lots of templates and stores them in deep nested
directories, you may consider using **Twig namespaces**, which create shortcuts
to template directories.
Registering your own Namespaces
-------------------------------
Suppose that you're using some third-party library that includes Twig templates
that live in ``vendor/acme/foo-bar/templates/``. This path is too long, so you
can define a ``foo_bar`` Twig namespace as a shortcut.
First, register a namespace for this directory:
.. configuration-block::
.. code-block:: yaml
# config/packages/twig.yaml
twig:
# ...
paths:
'%kernel.project_dir%/vendor/acme/foo-bar/templates': foo_bar
.. code-block:: xml
<!-- config/packages/twig.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:twig="http://symfony.com/schema/dic/twig"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">
<twig:config debug="%kernel.debug%" strict-variables="%kernel.debug%">
<twig:path namespace="foo_bar">%kernel.project_dir%/vendor/acme/foo-bar/templates</twig:path>
</twig:config>
</container>
.. code-block:: php
// config/packages/twig.php
$container->loadFromExtension('twig', [
'paths' => [
'%kernel.project_dir%/vendor/acme/foo-bar/templates' => 'foo_bar',
],
]);
The registered namespace is called ``foo_bar``, but you must prefix the ``@``
character when using it in templates (that's how Twig can differentiate
namespaces from regular paths). Assuming there's a file called ``sidebar.twig``
in the ``vendor/acme/foo-bar/templates/`` directory, you can refer to it as:
.. code-block:: twig
{{ include('@foo_bar/sidebar.twig') }}
Execute this command to verify if your template name is correct and know which
template file will be loaded:
.. code-block:: terminal
$ php bin/console debug:twig @foo_bar/sidebar.twig
Multiple Paths per Namespace
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A single Twig namespace can be associated with multiple paths. The order in
which paths are configured is very important, because Twig will always load
the first template that exists, starting from the first configured path. This
feature can be used as a fallback mechanism to load generic templates when the
specific template doesn't exist.
.. configuration-block::
.. code-block:: yaml
# config/packages/twig.yaml
twig:
# ...
paths:
'%kernel.project_dir%/vendor/acme/themes/theme1': theme
'%kernel.project_dir%/vendor/acme/themes/theme2': theme
'%kernel.project_dir%/vendor/acme/themes/common': theme
.. code-block:: xml
<!-- config/packages/twig.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:twig="http://symfony.com/schema/dic/twig"
xsi:schemaLocation="http://symfony.com/schema/dic/services
https://symfony.com/schema/dic/services/services-1.0.xsd">
<twig:config debug="%kernel.debug%" strict-variables="%kernel.debug%">
<twig:path namespace="theme">%kernel.project_dir%/vendor/acme/themes/theme1</twig:path>
<twig:path namespace="theme">%kernel.project_dir%/vendor/acme/themes/theme2</twig:path>
<twig:path namespace="theme">%kernel.project_dir%/vendor/acme/themes/common</twig:path>
</twig:config>
</container>
.. code-block:: php
// config/packages/twig.php
$container->loadFromExtension('twig', [
'paths' => [
'%kernel.project_dir%/vendor/acme/themes/theme1' => 'theme',
'%kernel.project_dir%/vendor/acme/themes/theme2' => 'theme',
'%kernel.project_dir%/vendor/acme/themes/common' => 'theme',
],
]);
Now, you can use the same ``@theme`` namespace to refer to any template located
in the previous three directories:
.. code-block:: twig
{{ include('@theme/header.twig') }}

View File

@@ -1,140 +0,0 @@
.. index::
single: Templating; Render template without custom controller
How to Render a Template without a custom Controller
====================================================
Usually, when you need to create a page, you need to create a controller
and render a template from within that controller. But if you're rendering
a simple template that doesn't need any data passed into it, you can avoid
creating the controller entirely, by using the built-in
:class:`Symfony\\Bundle\\FrameworkBundle\\Controller\\TemplateController`
controller.
For example, suppose you want to render a ``static/privacy.html.twig``
template, which doesn't require that any variables are passed to it. You
can do this without creating a controller:
.. configuration-block::
.. code-block:: yaml
# config/routes.yaml
acme_privacy:
path: /privacy
controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController
defaults:
template: static/privacy.html.twig
methods: GET
.. code-block:: xml
<!-- config/routes.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd">
<route id="acme_privacy"
path="/privacy"
controller="Symfony\Bundle\FrameworkBundle\Controller\TemplateController"
methods="GET">
<default key="template">static/privacy.html.twig</default>
</route>
</routes>
.. code-block:: php
// config/routes.php
use Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$routes->add('acme_privacy', '/privacy')
->controller(TemplateController::class)
->methods(['GET'])
->defaults([
'template' => 'static/privacy.html.twig',
])
;
};
The ``TemplateController`` will render whatever template you've passed as the
``template`` default value.
You can also use this trick when rendering embedded controllers
from within a template. But since the purpose of rendering a controller from
within a template is typically to prepare some data in a custom controller,
this is probably only useful if you'd like to cache this page partial (see
:ref:`templating-no-controller-caching`).
.. code-block:: twig
{{ render(url('acme_privacy')) }}
.. _templating-no-controller-caching:
Caching the static Template
---------------------------
Since templates that are rendered in this way are typically static, it might
make sense to cache them. Fortunately, you can configure your route to control
exactly how your page is cached:
.. configuration-block::
.. code-block:: yaml
# config/routes.yaml
acme_privacy:
path: /privacy
controller: Symfony\Bundle\FrameworkBundle\Controller\TemplateController
defaults:
template: 'static/privacy.html.twig'
maxAge: 86400
sharedAge: 86400
methods: GET
.. code-block:: xml
<!-- config/routes.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd">
<route id="acme_privacy"
path="/privacy"
controller="Symfony\Bundle\FrameworkBundle\Controller\TemplateController"
methods="GET">
<default key="template">static/privacy.html.twig</default>
<default key="maxAge">86400</default>
<default key="sharedAge">86400</default>
</route>
</routes>
.. code-block:: php
// config/routes.php
use Symfony\Bundle\FrameworkBundle\Controller\TemplateController;
use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator;
return function (RoutingConfigurator $routes) {
$routes->add('acme_privacy', '/privacy')
->controller(TemplateController::class)
->methods(['GET'])
->defaults([
'template' => 'static/privacy.html.twig',
'maxAge' => 86400,
'sharedAge' => 86400,
])
;
};
The ``maxAge`` and ``sharedAge`` values are used to modify the Response
object created in the controller. For more information on caching, see
:doc:`/http_cache`.
There is also a ``private`` variable (not shown here). By default, the Response
will be made public, as long as ``maxAge`` or ``sharedAge`` are passed.
If set to ``true``, the Response will be marked as private.

View File

@@ -1,19 +0,0 @@
.. index::
single: Templating; Linting
single: Twig; Linting
single: Templating; Syntax Check
single: Twig; Syntax Check
How to Check the Syntax of Your Twig Templates
==============================================
You can check for syntax errors in Twig templates using the ``lint:twig``
console command:
.. code-block:: terminal
# You can check by filename:
$ php bin/console lint:twig templates/article/recent_list.html.twig
# or by directory:
$ php bin/console lint:twig templates/

View File

@@ -4,26 +4,24 @@
How to Write a custom Twig Extension
====================================
If you need to create custom Twig functions, filters, tests or more, you'll need
to create a Twig extension. You can read more about `Twig Extensions`_ in the Twig
documentation.
`Twig Extensions`_ allow to create custom Twig functions, filters and more to
use them in your templates.
.. tip::
Before writing your own Twig extension, check if the filter/function that you
need is already implemented in the `default Twig filters and functions`_ or the
:doc:`Twig filters and functions added by Symfony </reference/twig_reference>`.
Check also the `official Twig extensions`_, which add commonly needed filters
and functions and can be installed in your application as follows:
Before writing your own Twig extension, check if the filter/function that
you need is already implemented in the :doc:`Symfony Twig extensions </reference/twig_reference>`.
Check also the `official Twig extensions`_, which can be installed in your
application as follows:
.. code-block:: terminal
.. code-block:: terminal
$ composer require twig/extensions
$ composer require twig/extensions
Create the Extension Class
--------------------------
Suppose you want to create a new filter called ``price`` that formats a number into
money:
Suppose you want to create a new filter called ``price`` that formats a number
into money:
.. code-block:: twig
@@ -94,24 +92,17 @@ Next, register your class as a service and tag it with ``twig.extension``. If yo
using the :ref:`default services.yaml configuration <service-container-services-load-example>`,
you're done! Symfony will automatically know about your new service and add the tag.
Optionally, execute this command to confirm that your new filter was
successfully registered:
You can now start using your filter in any Twig template. Optionally, execute
this command to confirm that your new filter was successfully registered:
.. code-block:: terminal
# display all information about Twig
$ php bin/console debug:twig
# display only the information about a specific filter
$ php bin/console debug:twig --filter=price
You can now start using your filter in any Twig template.
.. tip::
Run the following command to verify that the filters and functions created
by your extensions are successfully registered:
.. code-block:: terminal
$ php bin/console debug:twig
.. _lazy-loaded-twig-extensions:
Creating Lazy-Loaded Twig Extensions
@@ -184,6 +175,7 @@ If you're using the default ``services.yaml`` configuration, this will already
work! Otherwise, :ref:`create a service <service-container-creating-service>`
for this class and :doc:`tag your service </service_container/tags>` with ``twig.runtime``.
.. _`Twig Extensions`: https://twig.symfony.com/doc/2.x/advanced.html#creating-an-extension
.. _`default Twig filters and functions`: https://twig.symfony.com/doc/2.x/#reference
.. _`official Twig extensions`: https://github.com/twigphp/Twig-extensions
.. _`global variables`: https://twig.symfony.com/doc/2.x/advanced.html#id1
.. _`Twig Extensions`: https://twig.symfony.com/doc/2.x/advanced.html#creating-an-extension