Matthias Andreas Benkard | 12a5735 | 2021-12-28 18:02:04 +0100 | [diff] [blame^] | 1 | ``macro`` |
| 2 | ========= |
| 3 | |
| 4 | Macros are comparable with functions in regular programming languages. They |
| 5 | are useful to reuse template fragments to not repeat yourself. |
| 6 | |
| 7 | Macros are defined in regular templates. |
| 8 | |
| 9 | Imagine having a generic helper template that define how to render HTML forms |
| 10 | via macros (called ``forms.html``): |
| 11 | |
| 12 | .. code-block:: html+twig |
| 13 | |
| 14 | {% macro input(name, value, type = "text", size = 20) %} |
| 15 | <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}"/> |
| 16 | {% endmacro %} |
| 17 | |
| 18 | {% macro textarea(name, value, rows = 10, cols = 40) %} |
| 19 | <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value|e }}</textarea> |
| 20 | {% endmacro %} |
| 21 | |
| 22 | Each macro argument can have a default value (here ``text`` is the default value |
| 23 | for ``type`` if not provided in the call). |
| 24 | |
| 25 | Macros differ from native PHP functions in a few ways: |
| 26 | |
| 27 | * Arguments of a macro are always optional. |
| 28 | |
| 29 | * If extra positional arguments are passed to a macro, they end up in the |
| 30 | special ``varargs`` variable as a list of values. |
| 31 | |
| 32 | But as with PHP functions, macros don't have access to the current template |
| 33 | variables. |
| 34 | |
| 35 | .. tip:: |
| 36 | |
| 37 | You can pass the whole context as an argument by using the special |
| 38 | ``_context`` variable. |
| 39 | |
| 40 | Importing Macros |
| 41 | ---------------- |
| 42 | |
| 43 | There are two ways to import macros. You can import the complete template |
| 44 | containing the macros into a local variable (via the ``import`` tag) or only |
| 45 | import specific macros from the template (via the ``from`` tag). |
| 46 | |
| 47 | To import all macros from a template into a local variable, use the ``import`` |
| 48 | tag: |
| 49 | |
| 50 | .. code-block:: twig |
| 51 | |
| 52 | {% import "forms.html" as forms %} |
| 53 | |
| 54 | The above ``import`` call imports the ``forms.html`` file (which can contain |
| 55 | only macros, or a template and some macros), and import the macros as items of |
| 56 | the ``forms`` local variable. |
| 57 | |
| 58 | The macros can then be called at will in the *current* template: |
| 59 | |
| 60 | .. code-block:: html+twig |
| 61 | |
| 62 | <p>{{ forms.input('username') }}</p> |
| 63 | <p>{{ forms.input('password', null, 'password') }}</p> |
| 64 | |
| 65 | Alternatively you can import names from the template into the current namespace |
| 66 | via the ``from`` tag: |
| 67 | |
| 68 | .. code-block:: html+twig |
| 69 | |
| 70 | {% from 'forms.html' import input as input_field, textarea %} |
| 71 | |
| 72 | <p>{{ input_field('password', '', 'password') }}</p> |
| 73 | <p>{{ textarea('comment') }}</p> |
| 74 | |
| 75 | .. tip:: |
| 76 | |
| 77 | When macro usages and definitions are in the same template, you don't need to |
| 78 | import the macros as they are automatically available under the special |
| 79 | ``_self`` variable: |
| 80 | |
| 81 | .. code-block:: html+twig |
| 82 | |
| 83 | <p>{{ _self.input('password', '', 'password') }}</p> |
| 84 | |
| 85 | {% macro input(name, value, type = "text", size = 20) %} |
| 86 | <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}"/> |
| 87 | {% endmacro %} |
| 88 | |
| 89 | Macros Scoping |
| 90 | -------------- |
| 91 | |
| 92 | The scoping rules are the same whether you imported macros via ``import`` or |
| 93 | ``from``. |
| 94 | |
| 95 | Imported macros are always **local** to the current template. It means that |
| 96 | macros are available in all blocks and other macros defined in the current |
| 97 | template, but they are not available in included templates or child templates; |
| 98 | you need to explicitly re-import macros in each template. |
| 99 | |
| 100 | Imported macros are not available in the body of ``embed`` tags, you need |
| 101 | to explicitly re-import macros inside the tag. |
| 102 | |
| 103 | When calling ``import`` or ``from`` from a ``block`` tag, the imported macros |
| 104 | are only defined in the current block and they override macros defined at the |
| 105 | template level with the same names. |
| 106 | |
| 107 | When calling ``import`` or ``from`` from a ``macro`` tag, the imported macros |
| 108 | are only defined in the current macro and they override macros defined at the |
| 109 | template level with the same names. |
| 110 | |
| 111 | Checking if a Macro is defined |
| 112 | ------------------------------ |
| 113 | |
| 114 | You can check if a macro is defined via the ``defined`` test: |
| 115 | |
| 116 | .. code-block:: twig |
| 117 | |
| 118 | {% import "macros.twig" as macros %} |
| 119 | |
| 120 | {% from "macros.twig" import hello %} |
| 121 | |
| 122 | {% if macros.hello is defined -%} |
| 123 | OK |
| 124 | {% endif %} |
| 125 | |
| 126 | {% if hello is defined -%} |
| 127 | OK |
| 128 | {% endif %} |
| 129 | |
| 130 | Named Macro End-Tags |
| 131 | -------------------- |
| 132 | |
| 133 | Twig allows you to put the name of the macro after the end tag for better |
| 134 | readability (the name after the ``endmacro`` word must match the macro name): |
| 135 | |
| 136 | .. code-block:: twig |
| 137 | |
| 138 | {% macro input() %} |
| 139 | ... |
| 140 | {% endmacro input %} |