macro

Las macros son comparables con las funciones en los lenguajes de programación regulares. Son útiles para reutilizar fragmentos de plantilla y no repetirse.

Las macros se definen en plantillas regulares.

Imagina tener una plantilla de ayuda genérica que define cómo renderizar formularios HTML mediante macros (llamada forms.twig):

{% macro input(name, value, type = "text", size = 20) %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}"/>
{% endmacro %}

{% macro textarea(name, value, rows = 10, cols = 40) %}
    <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value|e }}</textarea>
{% endmacro %}

Cada argumento de macro puede tener un valor predeterminado (aquí text es el valor predeterminado para type si no se proporciona en la llamada).

Las macros difieren de las funciones PHP nativas en algunas formas:

  • Los argumentos de una macro siempre son opcionales.
  • Si se pasan argumentos posicionales adicionales a una macro, terminan en la variable especial varargs como una lista de valores.

Pero al igual que con las funciones PHP, las macros no tienen acceso a las variables actuales de la plantilla.

Tip

Puedes pasar todo el contexto como argumento usando la variable especial _context.

Importando Macros

Hay dos formas de importar macros. Puedes importar la plantilla completa que contiene las macros en una variable local (a través de la etiqueta import) o importar solo macros específicas de la plantilla (a través de la etiqueta from).

Para importar todas las macros de una plantilla en una variable local, usa la etiqueta import:

{% import "forms.html.twig" as forms %}

La llamada import anterior importa el archivo forms.html.twig (que puede contener solo macros, o una plantilla y algunas macros), e importa las macros como atributos de la variable local forms.

Las macros luego pueden ser llamadas a voluntad en la plantilla actual:

<p>{{ forms.input('username') }}</p>
<p>{{ forms.input('password', null, 'password') }}</p>
{# También puedes usar argumentos con nombre #}
<p>{{ forms.input(name: 'password', type: 'password') }}</p>

Alternativamente, puedes importar nombres de la plantilla al espacio de nombres actual a través de la etiqueta from:

{% from 'forms.html.twig' import input as input_field, textarea %}

<p>{{ input_field('password', '', 'password') }}</p>
<p>{{ input_field(name: 'password', type: 'password') }}</p>
<p>{{ textarea('comment') }}</p>

Caution

Como las macros importadas vía from se llaman como funciones, ten cuidado de que no oculten funciones existentes:

{% from 'forms.html.twig' import input as include %}

{# include se refiere a la macro y no a la función incorporada "include" #}
{{ include() }}

Tip

Cuando los usos y definiciones de macros están en la misma plantilla, no necesitas importar las macros ya que están automáticamente disponibles bajo la variable especial _self:

<p>{{ _self.input('password', '', 'password') }}</p>

{% macro input(name, value, type = "text", size = 20) %}
    <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}"/>
{% endmacro %}

Ámbito de las Macros

Las reglas de ámbito son las mismas ya sea que hayas importado macros vía import o from.

Las macros importadas son siempre locales a la plantilla actual. Esto significa que las macros están disponibles en todos los bloques y otras macros definidas en la plantilla actual, pero no están disponibles en plantillas incluidas o plantillas hijas; necesitas reimportar explícitamente las macros en cada plantilla.

Las macros importadas no están disponibles en el cuerpo de las etiquetas embed, necesitas reimportar explícitamente las macros dentro de la etiqueta.

Cuando llamas a import o from desde una etiqueta block, las macros importadas solo se definen en el bloque actual y ocultan las macros definidas a nivel de plantilla con los mismos nombres.

Comprobando si una Macro está definida

Puedes comprobar si una macro está definida a través de la prueba defined:

{% import "macros.html.twig" as macros %}

{% from "macros.html.twig" import hello %}

{% if macros.hello is defined -%}
    OK
{% endif %}

{% if hello is defined -%}
    OK
{% endif %}

Etiquetas de Fin de Macro Nombradas

Twig te permite poner el nombre de la macro después de la etiqueta de fin para una mejor legibilidad (el nombre después de la palabra endmacro debe coincidir con el nombre de la macro):

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