mirror of
https://github.com/symfony/symfony-docs.git
synced 2026-03-23 16:22:10 +01:00
Reworded all the docs related to templates and Twig
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -57,6 +57,8 @@ which is almost equivalent to the more verbose, but also more flexible,
|
||||
$_SERVER
|
||||
);
|
||||
|
||||
.. _accessing-request-data:
|
||||
|
||||
Accessing Request Data
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -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/*
|
||||
|
||||
@@ -123,6 +123,8 @@ new kernel.
|
||||
.. index::
|
||||
single: Configuration; Debug mode
|
||||
|
||||
.. _debug-mode:
|
||||
|
||||
Debug Mode
|
||||
~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -8,5 +8,5 @@ Getting Started
|
||||
/page_creation
|
||||
/routing
|
||||
/controller
|
||||
/templating
|
||||
/templates
|
||||
/configuration
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
93
routing.rst
93
routing.rst
@@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -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
1100
templates.rst
Normal file
File diff suppressed because it is too large
Load Diff
820
templating.rst
820
templating.rst
@@ -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 <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
|
||||
@@ -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::
|
||||
|
||||
|
||||
@@ -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`.
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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 <script>alert('hello!')</script>
|
||||
|
||||
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
|
||||
@@ -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
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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.
|
||||
@@ -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') }}
|
||||
@@ -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.
|
||||
@@ -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/
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user