Переопределение macro
Наследование в Twig очень мощная штука, но не хватает тут одного - переопределения макросов.Суть задачи в следующем: есть файл с макросами macro.twig
{% macro test() %}
Hello {{ _self.test_1() }}
{% endmacro %}
{% macro test_1() %}
World
{% endmacro %}
Из одного макроса вызываем второй, в результате работы {{ test() }} мы получим уже изрядно намозоливший «Hello World».У нас же задача переопределить макрос test_1.
Сразу код, комментарии ниже:
{% macro macro_extend( macroName, macroOptions, mergeList ) %}
{% set source_ %}
{% for path in mergeList %}
{{ source(path) }}
{% endfor %}
{% endset %}
{% set args %}
{% for index in macroOptions|keys %}
macroOptions[{{ index }}]
{% endfor %}
{% endset %}
{% set controll = '{{ _self.' ~ macroName ~ '(' ~ args ~ ') }}' %}
{{ include(template_from_string( source_ ~controll )) }}
{% endmacro %}
Для удобства создаем макрос extend, который как аргументы принимает:
macroName
- имя вызываемого макроса;macroOptions
- передаваемые в макрос аргументы в виде массива, где каждый элемент массива является одним аргументом для вызываемого макроса;mergeList
- список файлов, которые будут участвовать в предопределении, чем больше индекс, тем выше приоритет при определении.
Основной смысл затеи - собрать все макросы в одно место и вызвать нужный. Это все можно сделать при помощи source, include и template_from_string и магического _self.
Есть одна особенность в парсере твига для макросов: если парсер натыкается на два макроса названные одинаково, то он запомнит последний из них, то есть:
{% macro test() %}
test 1
{% endmacro %}
{% macro test() %}
test 2
{% endmacro %}
Результатом вызова {{ test() }} будет test 2. Это-то нам и поможет переопределять макросы так, как нам нужно.Чтобы сделать вызов определенного макроса из цепочки на лету нам понадобится _self, он ссылается на текущую область видимости, и через нее можно вызвать нужный нам макрос.
Вот, собственно, и вся хитрость, которая облегчит жизнь при построении сложных шаблонов с многочисленными контроллами.
PS: Пример вызова моего макроса
{% from 'macro_extend.twig' import macro_extend %}
{{ macro_extend('test', [], [
'test.twig',
'test2.twig'
]) }}