11/30/2015
Extending a parent Twig block with parent()
Twig blocks behave like methods on a class. A child template that extends a parent and then defines a block of the same name replaces the parent's version entirely, in the same way an overridden method replaces the one it overrides.
That is usually fine for a content block and almost never what you wanted
for a block holding stylesheets or scripts, because the parent's are gone
the moment the child defines its own. parent() puts them back:
{% extends 'base.html.twig' %}
{% block stylesheets %}
{{ parent() }}
<link rel="stylesheet" href="{{ asset('css/checkout.css') }}">
{% endblock %}
Without the parent() call, that child page loads checkout.css and
nothing else — every stylesheet the base template declared is silently
dropped. The symptom is a page that looks unstyled for no visible reason,
on one route only.
The template name
'base.html.twig' is a path relative to templates/. If you are reading
an older example that says something like
MainBundle::Base:main.html.twig, that is Symfony 2 bundle notation and
it was removed in Symfony 4.0. Templates inside a bundle now use
@BundleName/path/to/template.html.twig, and templates in your own
application are just their path under templates/.
Where it also helps
parent() works in any block, not only the asset ones. A base template
that sets a default page title is the other common case:
{# templates/base.html.twig #}
{% block title %}Belchamber Tools{% endblock %}
{# templates/article/show.html.twig #}
{% block title %}{{ article.title }} - {{ parent() }}{% endblock %}
One place it does not work is a block defined in the same template rather
than inherited — parent() needs a parent block to reach for, and
calling it without one is a Twig error rather than an empty string.