macro

Macros are similar to functions within regular programing languages. They are often used to output reusable HTML code.

However, they differ from programing functions in a few ways.

  • Default values for variables are specified using the default filter within the macro body, not in the macro definition.
  • Arguments of a macro are always optional. There is no need to specify that some are required and some are optional.
  • If you pass extra arguments that were not specified in the macro definition, then the extra arguments are accessed through the special varargs variable as a list of values.

Macros do not have access to any variables within the template context that they are used. They can only access variable values passed to them, or to variables created within the macro.

You can, however, pass then entire template context as an argument by using the special _context variable.

Example

The example that we'll reuse throughout this page is a macro to output a form tag.

{% macro input(label, name, value, type, size, placeholder) %}
  <label>{{ label }}
    <input type="{{ type|default('text') }}" name="{{ name }}"{% if value %} value="{{ value }}"{% endif %} size="{{ size|default(30) }}{% if placeholder %} placeholder={{ placeholder }}"{% endif %}>
  </label>
{% endmacro %}

Note that you must include the {% endmacro %} tag after the end of the macro code.

Using a macro

In order to first use a macro you must import it into the current template.

Lets assume that in our example we create a folder called "macros" within our theme folder and create a template file called "forms.twig" to hold our input macro.

{% import 'macros/forms' as forms %}
<form action="/page" method="post">
  <p>{{ forms.input('User Name', 'username') }}</p>
  <p>{{ forms.input('Password', 'password', null, 'password' }}</p>
  <p>{{ forms.input('Your Name', 'name', null, null, 40, 'Enter your full name') }}</p>
</form>

The above code will import the forms template located in the "macros" folder and assign each macro to the forms variable. We could have named our variable anything. It didn't have to be "forms". It could have been "macros", "formInputs", or anything else.

If we had other macros in the forms template file then we could access those macros using the forms.macroName format.

A template file containing macros that is imported into another template can only contain macros. No other HTML or Twig code is allowed.

You can, however, define macros within an existing template if you only plan to use that macro within that template.

Let's say that we have a form template and want to define the "input" macro within that template. The only two differences from having the macro in a separate template file are

  1. The macro can only be used in the current template that it's defined in.
  2. The import process is slightly different. It's done using the special _self variable instead of the template name.

 

{% macro input(label, name, value, type, size, placeholder) %}
  <label>{{ label }}
    <input type="{{ type|default('text') }}" name="{{ name }}"{% if value %} value="{{ value }}"{% endif %} size="{{ size|default(30) }}{% if placeholder %} placeholder={{ placeholder }}"{% endif %}>
  </label>
{% endmacro %}
{% import _self as fields %}
<form action="/page" method="post">
  <p>{{ fields.input('User Name', 'username') }}</p>
  <p>{{ fields.input('Password', 'password', null, 'password' }}</p>
  <p>{{ fields.input('Your Name', 'name', null, null, 40, 'Enter your full name') }}</p>
</form>

Using a macro within another macro

If you want you use a macro within another macro in the same file then you can access it with the special _self variable.

{% macro input(name, value, type, size, placeholder) %}
    <input type="{{ type|default('text') }}" name="{{ name }}"{% if value %} value="{{ value }}"{% endif %} size="{{ size|default(30) }}{% if placeholder %} placeholder={{ placeholder }}"{% endif %}>
{% endmacro %}
{% macro inputField(label, name, value, type, size, placeholder) %}
  <label>{{ label }}
    {{ _self.input(name, value, type, size, placeholder) }}
  </label>
{% endmacro %}

You can also use a macro that is located within a separate template file in a macro. You still need to import the macro, you just use the template path.

{% macro inputField(label, name, value, type, size, placeholder) %}
  {% import 'macros/forms' as forms %}
  <label>{{ label }}
    {{ forms.input(name, value, type, size, placeholder) }}
  </label>
{% endmacro %}

Named macro end tags

To help with readability, you can put the name of the macro after endmacro in the end tag.

{% macro input() %}
...
{% endmacro input %}

< Back to the list of tags