After several months, I am posting an answer for further reference to this question. I also added a description for extends and import and macro and embed for more clearance:
There are various types of code inheritance and reuse in Twig:
Enable
The main goal is code reuse . As an example, consider using header.html.twig and footer.html.twig inside base.html.twig .
header.html.twig
<nav> <div>Homepage</div> <div>About</div> </nav>
base.html.twig
{% include 'header.html.twig' %} <main>{% block main %}{% endblock %}</main>
Expands
The main goal is vertical inheritance . Consider the example base.html.twig inside homepage.html.twig and about.html.twig .
base.html.twig
{% include 'header.html.twig' %} <main>{% block main %}{% endblock %}</main>
homepage.html.twig
{% extends 'base.html.twig' %} {% block main %} <p>You are at the homepage</p> {% endblock %}
about.html.twig
{% extends 'base.html.twig' %} {% block main %} <p>You are at the about page</p> {% endblock %}
Using
The main goal is the reuse of horizontal scanning . Consider using sidebar.html.twig inside single.product.html.twig (extends product.layout.html.twig ) and single.service.html.twig (extends service.layout.html.page ) pages. (it's like macros, but for blocks)
sidebar.html.twig
<aside>{% block sidebar %}{% endblock %}</aside>
single.product.html.twig
{% extends 'product.layout.html.twig' %} {% use 'sidebar.html.twig' %} {% block main %} <p>You are at the product page for product number 123</p> {% endblock %}
single.service.html.twig
{% extends 'service.layout.html.twig' %} {% use 'sidebar.html.twig' %} {% block main %} <p>You are at the service page for service number 456</p> {% endblock %}
Macro
The main goal is with the ability to reuse markup in many templates with variables . Consider a function that receives some variables and displays some markup.
form.html.twig
{% macro input(name, value, type) %} <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" }}" /> {% endmacro %}
profile.service.html.twig
{% import "forms.html.twig" as forms %} <div>{{ forms.input('username') }}</div>
Embed
The main goal is to block the block . It has the functionality of both Use and Include . Consider embedding pagination.html.twig in product.table.html.twig and service.table.html.twig .
pagination.html.twig
<div> <div>{% block first %}{% endblock %}</div> {% for i in (min + 1)..(max - 1) %} <div>{{ i }}</div> {% endfor %} <div>{% block last %}{% endblock %}</div> </div>
product.table.html.twig
{% set min, max = 1, products.itemPerPage %} {% embed 'pagination.html.twig' %} {% block first %}First Product Page{% endblock %} {% block last %}Last Product Page{% endblock %} {% endembed %}
service.table.html.twig
{% set min, max = 1, services.itemPerPage %} {% embed 'pagination.html.twig' %} {% block first %}First Service Page{% endblock %} {% block last %}Last Service Page{% endblock %} {% endembed %}
Note that the embedded file ( pagination.html.twig here) has access to the current context ( min , max here). You can also pass additional variables to the embedded file:
pagination.html.twig
<p>{{ count }} items</p> <div> <div>{% block first %}{% endblock %}</div> {% for i in (min + 1)..(max - 1) %} <div>{{ i }}</div> {% endfor %} <div>{% block last %}{% endblock %}</div> </div>
product.table.html.twig
{% set min, max = 1, products|length %} {% embed 'pagination.html.twig' with {'count': products|length } %} {% block first %}First Product Page{% endblock %} {% block last %}Last Product Page{% endblock %} {% endembed %}