Начиная с версии 0.4 в Blitz практически без изменений была добавлена функциональность движка php_templates. Суть контекстов заключается в следующем. Обычно мы имеем дело с «плоскими» шаблонами, в них есть либо переменные, либо какие-то операторы или вызовы, которые обязательно исполняются. Контексты - это подшаблоны, которые не используются до тех пор, пока контроллер шаблона явно это не укажет. Например, если у нас есть php-код
переменная: <?=$a?>, метод: <?=b()?>
, то оба куска этого кода будут всегда исполнены. Никакой иерархии нет, все php-шаблоны плоские. Теперь рассмотрим некий псевдокод с контекстами
переменная : {{ $a }}, контекст {{ BEGIN b }} что-то внутри {{ END }}
Здесь b — это контекст, который по умолчанию не будет использован (чаще используют термин «итерирован») - и вместо кода от BEGIN до END ничего не будет. Если контекст итерирован один раз, то в шаблоне появится результат исполнения внутренней части контекста. Если проитерировать дважды — результат исполнения внутренней части контекста два раза. Параметры у каждой итерации, разумеется, могут быть разными. Таким образом, для отображения списков достаточно просто итерировать контекст, описывающий элемент списка, для каждого элемента. Самое удобное заключается в том, что контексты могут быть вложены друг в друга. Каждый контекст однозначно определён своим путем — /root/node/item означает, что есть контекст root, внутри которого контекст node внутри которого item. Если итерировать родительский контекст с одними параметрами, потом вложенные контексты, потом снова родительские контексты с другими параметрами, а потом снова вложенные, то можно при помощи одного единственного шаблона сделать страницу абсолютно любой сложности. Есть базовые операции с контекстами — установить текущий контекст и итерировать контекст. Установка означает, что все вызовы по умолчанию работают с этим контекстом, тут есть хорошая аналогия с работой командной оболочке — установить текущий контекст в /root/node/item по смыслу то же самое что сделать cd в /root/node/item. А итерировать фактически означает «исполнить».
Передавая параметр context_path в любую из функций, вы можете передавать его в двух формах:
абсолютной
/context1/context2/context3
относительной
context2/context3
../context3
В Blitz внутри контекстов также доступны такие приятные мелочи как if()
, include()
и вызов пользовательского метода.
Следующий код выводит ужасно доставшее всех знакомое всем приветствие, запрятанное в трех вложенных контекстах.
Пример 7.1. Ужасно доставшее всех знакомое всем приветствие, запрятанное в трех вложенных контекстах
{{ BEGIN root }} {{ BEGIN node }} {{ BEGIN item }} hello, world {{ END }} {{ END }} {{ END }}
<? $T = new Blitz('tpl'); $T->iterate('/root/node/item'); echo $T->parse(); ?>
hello, world
Пример 7.2. Работа с простыми списками
{{ BEGIN row }}row #{{ $i }} {{ END }}
<? $T = new Blitz('tpl'); $max_num_list = 5; // use context & iterate $T->context('row'); for($i=0; $i<$max_num_list; $i++) { $T->iterate(); $T->set(array('i' => $i)); } // or just use block for($i=0; $i<$max_num_list; $i++) { $T->block('/row',array('i' => $i)); } echo $T->parse(); ?>
row #0 row #1 row #2 row #3 row #4 row #0 row #1 row #2 row #3 row #4
Метод block()
— удобная замена последовательным iterate()
и set()
, которые встречаются в коде очень часто именно вместе. Разумеется, в Blitz внутри контекста можно использовать и include()
, и if()
, и пользовательские методы. Переменные, установленные в родительских контекстах, «не видны» в дочерних. Если есть необходимость в глобальных переменных, которые будут «видны» в любом месте шаблона - можно использовать метод set_global()
вместо set()
.
Пример 7.3. Как при помощи вложенных контекстов строить более сложные списки
complex list example {{ BEGIN list; }} list #{{ $list_num }} {{ BEGIN list_empty; }} this list is empty {{ END }}{{ BEGIN list_item; }} row #{{ $i_row; }} {{ END }} {{ END }}
<? $T = new Blitz('tpl'); $max_num_list = 5; $max_num_item = 5; $T->context('/list'); for($i=0; $i<$max_num_list; $i++) { $T->block('',array('list_num' => $i)); $is_empty = $i%2; // emulate empty sub-lists if($is_empty) { $T->block('list_empty'); } else { for($j=0; $j<$max_num_item; $j++) { $T->block('list_item',array('i_row' => $i.':'.$j)); } } } echo $T->parse(); ?>
complex list example list #0 row #0:0 row #0:1 row #0:2 row #0:3 row #0:4 list #1 this list is empty list #2 row #2:0 row #2:1 row #2:2 row #2:3 row #2:4 list #3 this list is empty list #4 row #4:0 row #4:1 row #4:2 row #4:3 row #4:4
Фактически на этом простом механизме попеременных итераций вложенных контекстов реализуется абсолютно любая логика даже в одном единственном шаблоне.
В-общем, функционал контекстов достаточно мощный для того, что бы использовать шаблонный движок для сколь угодно сложных проектов.