Начиная с версии 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
Фактически на этом простом механизме попеременных итераций вложенных контекстов реализуется абсолютно любая логика даже в одном единственном шаблоне.
В-общем, функционал контекстов достаточно мощный для того, что бы использовать шаблонный движок для сколь угодно сложных проектов.