8000 Updated the docs for the new way to render partials/ESI/HInclude by fabpot · Pull Request #2121 · symfony/symfony-docs · GitHub
[go: up one dir, main page]

Skip to content

Updated the docs for the new way to render partials/ESI/HInclude #2121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 13, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions book/_security-2012-6431.rst.inc

This file was deleted.

111 changes: 64 additions & 47 deletions book/http_cache.rst
Original file line number Diff line number Diff line change
Expand Up @@ -881,58 +881,37 @@ matter), Symfony2 uses the standard ``render`` helper to configure ESI tags:

.. code-block:: jinja

{% render url('latest_news', { 'max': 5 }), {'standalone': true} %}
{# you can use a controller reference #}
{{ render_esi(controller('...:news', { 'max': 5 })) }}

{# ... or a URL #}
{{ render_esi(url('latest_news', { 'max': 5 })) }}

.. code-block:: php

<?php echo $view['actions']->render(
new ControllerReference('...:news', array('max' => 5)),
array('strategy' => 'esi'))
?>

<?php echo $view['actions']->render(
$view['router']->generate('latest_news', array('max' => 5), true),
array('standalone' => true)
array('strategy' => 'esi')
) ?>

.. include:: /book/_security-2012-6431.rst.inc

The ``render`` tag takes the absolute url to the embedded action. This means
that you need to define a new route to the controller that you're embedding:

.. code-block:: yaml

# app/config/routing.yml
latest_news:
pattern: /esi/latest-news/{m 8000 ax}
defaults: { _controller: AcmeNewsBundle:News:news }
requirements: { max: \d+ }

.. caution::

Unless you want this URL to be accessible to the outside world, you
should use Symfony's firewall to secure it (by allowing access to your
reverse proxy's IP range). See the :ref:`Securing by IP<book-security-securing-ip>`
section of the :doc:`Security Chapter </book/security>` for more information
on how to do this.

.. tip::
By using the ``esi`` rendering strategy (via the ``render_esi`` Twig
function), you tell Symfony2 that the action should be rendered as an ESI tag.
You might be wondering why you would want to use a helper instead of just
writing the ESI tag yourself. That's because using a helper makes your
application work even if there is no gateway cache installed.

The best practice is to mount all your ESI urls on a single prefix (e.g.
``/esi``) of your choice. This has two main advantages. First, it eases
the management of ESI urls as you can easily identify the routes used for ESI.
Second, it eases security management since securing all urls starting
with the same prefix is easier than securing each individual url. See
the above note for more details on securing ESI URLs.

By setting ``standalone`` to ``true`` in the ``render`` Twig tag, you tell
Symfony2 that the action should be rendered as an ESI tag. You might be
wondering why you would want to use a helper instead of just writing the ESI tag
yourself. That's because using a helper makes your application work even if
there is no gateway cache installed.

When standalone is ``false`` (the default), Symfony2 merges the included page
content within the main one before sending the response to the client. But
when standalone is ``true``, *and* if Symfony2 detects that it's talking
to a gateway cache that supports ESI, it generates an ESI include tag. But
if there is no gateway cache or if it does not support ESI, Symfony2 will
just merge the included page content within the main one as it would have
done were standalone set to ``false``.
When using the default ``render`` function (or setting the strategy to
``default``), Symfony2 merges the included page content within the main one
before sending the response to the client. But when using ``esi`` strategy,
*and* if Symfony2 detects that it's talking to a gateway cache that supports
ESI, it generates an ESI include tag. But if there is no gateway cache or if
it does not support ESI, Symfony2 will just merge the included page content
within the main one as it would have done if you had used ``render``.

.. note::

Expand All @@ -947,14 +926,52 @@ of the master page.

public function newsAction($max)
{
// ...
// ...

$response->setSharedMaxAge(60);
$response->setSharedMaxAge(60);
}

With ESI, the full page cache will be valid for 600 seconds, but the news
component cache will only last for 60 seconds.

When using a controller reference, the ESI tag should reference the embedded
action as an accessible URL so the gateway cache can fetch it independently of
the rest of the page. Of course, an action can't be accessed via a URL unless
it has a route that points to it. Symfony2 takes care of this via a generic
route and controller. For the ESI include tag to work properly, you must
define the ``_proxy`` route:

.. configuration-block::

.. code-block:: yaml

# app/config/routing.yml
_proxy:
resource: "@FrameworkBundle/Resources/config/routing/proxy.xml"
prefix: /proxy

.. code-block:: xml

<!-- app/config/routing.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 http://symfony.com/schema/routing/routing-1.0.xsd">

<import resource="@FrameworkBundle/Resources/config/routing/proxy.xml" prefix="/proxy" />
</routes>

.. code-block:: php

// app/config/routing.php
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection->addCollection($loader->import('@FrameworkBundle/Resources/config/routing/proxy.xml', '/proxy'));

return $collection;

One great advantage of this caching strategy is that you can make your
application as dynamic as needed and at the same time, hit the application as
little as possible.
Expand All @@ -967,7 +984,7 @@ little as possible.
obey the ``max-age`` directive and cache the entire page. And you don't
want that.

The ``render`` helper supports two other useful options:
The ``render_esi`` helper supports two other useful options:

* ``alt``: used as the ``alt`` attribute on the ESI tag, which allows you
to specify an alternative URL to be used if the ``src`` cannot be found;
Expand Down
82 changes: 21 additions & 61 deletions book/templating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,7 @@ Including this template from any other template is simple:
<h1>Recent Articles<h1>

{% for article in articles %}
{% include 'AcmeArticleBundle:Article:articleDetails.html.twig'
with {'article': article}
%}
{{ include('AcmeArticleBundle:Article:articleDetails.html.twig', {'article': article}) }}
{% endfor %}
{% endblock %}

Expand All @@ -551,7 +549,7 @@ Including this template from any other template is simple:
<?php endforeach; ?>
<?php $view['slots']->stop() ?>

The template is included using the ``{% include %}`` tag. Notice that the
The template is included using the ``{{ include() }}`` function. Notice that the
template name follows the same typical convention. The ``articleDetails.html.twig``
template uses an ``article`` variable. This is passed in by the ``list.html.twig``
template using the ``with`` command.
Expand Down Expand Up @@ -623,43 +621,8 @@ The ``recentList`` template is perfectly straightforward:
(e.g. ``/article/*slug*``). This is a bad practice. In the next section,
you'll learn how to do this correctly.

Even though this controller will only be used internally, you'll need to
create a route that points to the controller:

.. configuration-block::

.. code-block:: yaml

latest_articles:
pattern: /articles/latest/{max}
defaults: { _controller: AcmeArticleBundle:Article:recentArticles }

.. code-block:: 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 http://symfony.com/schema/routing/routing-1.0.xsd">

<route id="latest_articles" pattern="/articles/latest/{max}">
<default key="_controller">AcmeArticleBundle:Article:recentArticles</default>
</route>
</routes>

.. code-block:: php

use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;

$collection = new RouteCollection();
$collection->add('latest_articles', new Route('/articles/latest/{max}', array(
'_controller' => 'AcmeArticleBundle:Article:recentArticles',
)));

return $collection;

To include the controller, you'll need to refer to it using an absolute url:
To include the controller, you'll need to refer to it using the standard
string syntax for controllers (i.e. **bundle**:**controller**:**action**):

.. configuration-block::

Expand All @@ -669,7 +632,7 @@ To include the controller, you'll need to refer to it using an absolute url:

{# ... #}
<div id="sidebar">
{% render url('latest_articles', { 'max': 3 }) %}
{{ render(controller('AcmeArticleBundle:Article:recentArticles', { 'max': 3 })) }}
</div>

.. code-block:: html+php
Expand All @@ -679,12 +642,10 @@ To include the controller, you'll need to refer to it using an absolute url:
<!-- ... -->
<div id="sidebar">
<?php echo $view['actions']->render(
$view['router']->generate('latest_articles', array('max' => 3), true)
new ControllerReference('AcmeArticleBundle:Article:recentArticles', array('max' => 3))
) ?>
</div>

.. include:: /book/_security-2012-6431.rst.inc

Whenever you find that you need a variable or a piece of information that
you don't have access to in a template, consider rendering a controller.
Controllers are fast to execute and promote good code organization and reuse.
Expand All @@ -703,13 +664,20 @@ Symfony2 uses the standard ``render`` helper to configure ``hinclude`` tags:

.. code-block:: jinja

{% render url('...'), {'standalone': 'js'} %}
{{ render_hinclude(controller('...')) }}

{{ render_hinclude(url('...')) }}

.. code-block:: php

<?php echo $view['actions']->render(
new ControllerReference('...'),
array('strategy' => 'hinclude')
) ?>

<?php echo $view['actions']->render(
$view['router']->generate('...'),
array('standalone' => 'js')
array('strategy' => 'hinclude')
) ?>

.. note::
Expand Down Expand Up @@ -756,18 +724,14 @@ any global default templates that is defined):

.. code-block:: jinja

{% render '...:news' with
{},
{'standalone': 'js', 'default': 'AcmeDemoBundle:Default:content.html.twig'}
%}
{{ render_hinclude(controller('...'), {'default': 'AcmeDemoBundle:Default:content.html.twig'}) }}

.. code-block:: php

<?php echo $view['actions']->render(
'...:news',
array(),
new ControllerReference('...'),
array(
'standalone' => 'js',
'strategy' => 'hinclude',
'default' => 'AcmeDemoBundle:Default:content.html.twig',
)
) ?>
Expand All @@ -778,18 +742,14 @@ Or you can also specify a string to display as the default content:

.. code-block:: jinja

{% render '...:news' with
{},
{'standalone': 'js', 'default': 'Loading...'}
%}
{{ render_hinclude(controller('...'), {'default': 'Loading...'}) }}

.. code-block:: php

<?php echo $view['actions']->render(
'...:news',
array(),
new ControllerReference('...'),
array(
'standalone' => 'js',
'strategy' => 'hinclude',
'default' => 'Loading...',
)
) ?>
Expand Down
Loading
0