
Содержание
Список таблиц
Список примеров
Blitz родился весьма неоригинально, for fun. Однако, поигравшись с ним немного, мне показалось, что скорость, с которой он работает, и удобства, которые он предоставляет разработчику — стоят того, чтобы дать его поиграться коллегам. Основных «фишек» у Blitz три:
написан как PHP-модуль на Си, и является одним из самых быстрых движков;
имеет простой и интуитивно понятный синтаксис;
позволяет структурировать код удобным и легко читаемым образом.
Blitz поддерживает разделение и скрытие функционально различных частей шаблонов с помощью простого механизма: текст шаблона может содержать вызов методов объекта, который этим шаблоном управляет. Таким образом, достигается основная цель: шаблон не содержит большого количества блоков и контекстов, часто мешающих разобраться, что к чему. Напротив, даже в проекте со сложной логикой представления при правильном подходе шаблоны будут давать разработчику своеобразную «карту» всего проекта. Blitz также позволяет включать одни шаблоны в другие (аналог include) и поддерживает условный вывод переменных (аналог if).
Начиная с версии 0.4 в Blitz добавлен функционал движка php_templates. Теперь в Blitz можно создавать множество вложенных шаблонов внутри одного файла, это сильно упрощает жизнь для очень сложных шаблонов с одной стороны и улучшает показатели по производительности для ряда задач с другой.
Также с версии 0.4 есть экспериментальная поддержка работы с набором «упакованных» шаблонов (blitzpack), когда несколько шаблонов сначала единожды «компилируются» в бинарный формат, упаковываются в один файл, и затем работа ведется только с этой «бинарной пачкой» шаблонов, экономя время на файловых операциях и разборе шаблонов.
Мне бы не хотелось здесь следовать академической традиции и проводить подробный анализ других проектов. В любом случае, если вы научились эффективно использовать сам PHP в качестве шаблонного движка, обходясь без сторонних продуктов и библиотек — вы счастливый человек. Вы используете самый эффективный с точки зрения производительности подход, и если он вам удобен — придерживайтесь его. Если нет — попробуйте Blitz. Возможно, он вас приятно удивит ;)
Статус проекта — полуэкспериментальный, но я считаю текущую версию вполне работоспособной. В силу параноидального отношения к качеству проекта, 100%-я стабильность и обратная совместимость до версии 1.0 не гарантируется.
К сожалению, мне неизвестна ни одна простая, универсальная и по-настоящему корректная методика анализа производительности шаблонных движков. А результатами любых искусственных, или как их ещё принято называть, синтетических, тестов пользоваться нужно максимально осторожно. Тем не менее, здесь приводятся результаты двух тестов. Первый тест — классический, измеряющий скорость выполнения циклических итераций одного и того же шаблона. Тест крайне простой, но позволяющий достаточно условно разделить группы движков на «нормальные», «медленные» и «никуда не годные». Число итераций и переменных в блоке было взято по умолчанию (9 переменных, 50 итераций), результаты этого теста приведены в таблице 1. Как легко видеть, Blitz, по крайней мере, аутсайдером не является.
Таблица 2.1. Классический тест производительности
| Тестовая машина (A): XEON*2 2,4GHz (HT on) 2GB; linux php-4.3.10(fcgi) zps nginx blitz, php_templates: so-модули, CFLAGS: -g3 -O2 | |||
|---|---|---|---|
| № | Engine name | Time | Percentage |
| 1 | php | 0.000544 | 100% |
| 2 | blitz | 0.001008 | 185% |
| 3 | php_templates | 0.001812 | 333% |
| 4 | smarty | 0.002006 | 369% |
| 5 | str_replace | 0.003713 | 683% |
| 6 | phemplate | 0.004514 | 830% |
| 7 | fasttemplate | 0.006835 | 1256% |
| 8 | vtemplate | 0.009565 | 1758% |
| 9 | ultratemplate | 0.012993 | 2388% |
| 10 | templatepower | 0.017056 | 3135% |
| 11 | bugitemplate | 0.019989 | 3674% |
| 12 | phplib | 0.028053 | 5157% |
| 13 | profTemplate | 0.043104 | 7924% |
| 14 | xtemplate | 0.048799 | 8970% |
| Тестовая машина (B): PC PIV 2,8GHz (HT off) 1GB; linux-2.6.8 php-4.3.10 (Apache/1.3.33 static) zps blitz, php_templates: so-модули, CFLAGS -g -O2 | |||
|---|---|---|---|
| № | Engine name | Time | Percentage |
| 1 | php | 0.00045 | 100% |
| 2 | blitz | 0.000834 | 185% |
| 3 | php_templates | 0.001595 | 354% |
| 4 | smarty | 0.001694 | 376% |
| 5 | str_replace | 0.00373 | 829% |
| 6 | phemplate | 0.004215 | 937% |
| 7 | fasttemplate | 0.006139 | 1364% |
| 8 | vtemplate | 0.008755 | 1946% |
| 9 | ultratemplate | 0.012747 | 2833% |
| 10 | templatepower | 0.018678 | 4151% |
| 11 | bugitemplate | 0.019286 | 4286% |
| 12 | phplib | 0.025478 | 5662% |
| 13 | profTemplate | 0.045148 | 10033% |
| 14 | xtemplate | 0.048137 | 10697% |
Столь сильное отличие php от прочих движков объясняется тем, что весь код php-теста упакован в один файл, в то время для остальных есть два файла — php-файл контроллера и шаблонный файл, который парсится котроллером.
В результаты этого теста не включены некоторые известные шаблонные движки, такие как madtemplate, PEAR::Sigma и PEAR::HTML_Template_IT по простой причине: они не были установлены на тестовых машинах. Однако, насколько мне известно, эти проекты не являются кандидатами на попадание в пятерку лидеров. В этом можно убедиться, например, проведя онлайн-тесты самостоятельно, или скачав тестирующую программу.
Второй тест более приближен к полевым условиям. Он представляет собой тестирование некоторой динамической страницы, подготовленной с использованием разных движков, при помощи стандартной утилиты ab. Итак, у нас есть страница какого-то псевдопортала, содержащая:
ротирующиеся рекламные уши (3 шт.);
«полосатую» навигацию (~10 разделов);
горячие новости (~10 шт.);
список пользователи онлайн (~20 шт.);
голосовалка с вариантами ответов (3 ответа);
прочие переменные на странице (~5 шт).
Для тестирования было выбрано 4 подхода:
ugly php mess: используется только php, причем весь код полностью упакован в один файл, представляя собой эдакую «кашу». Такой прием практически никогда не встречается в реальных больших проектах, но включен в тесты исключительно ради интереса, поскольку очевидно является самым быстрым.
php includes: используется только php, функционально разные блоки (элементы списков) вынесены в отдельные файлы.
php_templates: один шаблон, на каждый функциональный блок — контекст.
blitz includes: разные шаблоны на каждый функциональный блок, подключаемые через include.
blitz ctx: один шаблон, на каждый функциональный блок — контекст.
blitz ctx arrays: один шаблон, на каждый функциональный блок — контекст, один вызов установки массива итераций.
blitzpack: разные шаблоны на каждый функциональный блок, упакованые в один blitzpack, подключаемые через include.
smarty: один шаблон, на функциональные блоки — циклы внутри шаблона.
Все данные упакованы в структуру в отдельном файле, который инклюдится во всех тестовых вариантах. Числа запросов в секунду, которое выполняет сервер для каждого из методов, представлены в таблице 2.
Таблица 2.2. Тест производительности приближенный к полевым условиям
| Тестовая машина(B), см. таблицу 1 | |
|---|---|
| ab -n20000 -c100, ZPS on | |
| ugly php mess | 1150 |
| blitz ctx arrays | 890 |
| blitz ctx | 825 |
| php includes | 770 |
| blitzpack | 725 |
| blitz incudes | 680 |
| smarty | 620 |
| php_templates | 615 |
| Тестовая машина(B), см. таблицу 1 | |
|---|---|
| ab -n20000 -c100, ZPS off | |
| ugly php mess | 660 |
| blitz ctx arrays | 590 |
| blitz ctx | 560 |
| php_templates | 450 |
| blitzpack | 440 |
| blitz incudes | 430 |
| php includes | 285 |
| smarty | 125 |
К сожалению, я не имел возможности провести тесты для других шаблонных движков (впрочем, код для этого теста доступен, вы можете добавить в него решения исходной задачи с использованием любых других средств). Поэтому ограничусь обобщенной интерпретацией этих результатов. То, что native PHP-код вместе с акселератором всегда будут быстрее прочих решений — очевидно. Правда, следует особенно подчеркнуть, что native в этом смысле — именно написанный программистом самим, а не «скомпилированный». В этом легко убедиться, заглянув внутрь любого «скомпилированного» шаблона: как правило, их код состоит из многомерных, довольно сложных для выполнения конструкций, значительно сложнее, чем написанный правильными руками код ;) Поскольку разница между Blitz и «правильным» методом php includes не является кардинальной, а все синтетические тесты позволяют лишь выявить группы приблизительно равных, можно с определенной долей уверенности считать методы разработки с использованием PHP, Blitz и php_templates примерно одинаковыми по производительности.
Следует также принять во внимание, что в реальном проекте разница в скорости между различными методами, скорее всего, будет ещё меньше. Во-первых, это связано с тем, что значительное время будет тратиться на работу с источниками данных (СУБД, различные сервисы и проч.). Во-вторых, отношение «количества» кода, относящегося к уровню представления, и прочего кода будет совершенно иным. Грубо говоря, view_code = full_code для тестов и пусть выигрыш на синтетическом тесте составляет даже десятки процентов. Но в реальном проекте часто выполняется соотношение view_code >> full_code, и поэтому выигрыш на уровне представления уже почти ничего не даст. Как вы могли заметить, почти все тесты были проведены с использованием акселератора из ZPS. Вряд ли сейчас можно представить крупный проект, в котором не используется акселератор, однако, акселератор акселератору рознь. И вполне возможно вы получите совершенно иные результаты при использовании, например, eAccelerator'a. В-общем, призываю вас не полагаться полностью на приведенные результаты. Скачивайте тесты, экспериментируйте на реальных задачах, и выбирайте те решения, которые дают выигрыш в вашем проекте.
Содержание
Blitz — расширение PHP, поставляемое пока исключительно в исходных кодах, поэтому его установка состоит из обычных шагов по сборке расширения:
tar zxvf blitz.tar.gz
cd blitz
phpize
./configure
make
make install
Вы можете протестировать Blitz запустив скрипт run-tests.sh.
run-tests (поставляется вместе с PHP).
bash>./run-tests.sh ===================================================================== CWD : /home/fisher/prj/blitz/tests PHP : /usr/local/bin/php PHP_SAPI : cli PHP_VERSION : 4.3.10 ZEND_VERSION: 1.3.0 PHP_OS : Linux - Linux fisher 2.6.8-24.19-smp #1 SMP Tue Nov 29 14:32:45 UTC 2005 i686 INI actual : /usr/local/lib/php.ini More .INIs : Extra dirs : ===================================================================== Running selected tests. PASS contexts [context.phpt] PASS errors and warnings [errors.phpt] PASS fetch [fetch.phpt] PASS complex fetch [fetch_cmplx.phpt] PASS predefined methods: if [if.phpt] PASS predefined methods: include [include.phpt] PASS user-defined methods [method.phpt] PASS method call from inner include [mfi.phpt] PASS variables [var.phpt]
После этого вы, возможно, захотите отредактировать свой php.ini, включив blitz в список расширений:
extension=blitz.so
Сборка blitz тестировалась на Linux 2.6 (i386) и Windows XP. Пользователи Windows могут воспользоваться готовыми Win32-бинарниками.
Таблица 4.1. Параметры конфигурации
| Имя | Описание | Значение по умолчанию | Изменяемость |
|---|---|---|---|
| blitz.tag_open | открывающий тег | {{ | PHP_INI_ALL |
| blitz.tag_close | закрывающий тег | }} | PHP_INI_ALL |
| blitz.var_prefix | префикс переменной | $ | PHP_INI_ALL |
$test, вы должны вставить следующий код в ваш шаблон: {{ $test }}Как и во многих других шаблонных движках двумя базовыми сущностями проекта, которые использует Blitz, являются собственно шаблон и объект, управляющий выполнением этого шаблона (контроллер шаблона).
Класс Blitz — внутренний класс расширения, управляющий шаблоном. Первый и единственный параметр конструктора класса — имя шаблона. Этот параметр необязателен — можно загрузить шаблон из переменной PHP используя метод load().
Blitz не поддерживает по принципиальным соображениям сложные выражения:
{{if(if($foo, 0, 1), 'bar', 'foobar')}}
Данный код работать не будет. Не надо превращать код в спагетти.
Начиная с версии 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() и вызов пользовательского метода.
Следующий код выводит ужасно доставшее всех знакомое всем приветствие, запрятанное в трех вложенных контекстах.
Пример 6.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
Пример 6.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(), и пользовательские методы. Переменные, установленные в родительских контекстах, «не видны» в дочерних. Если есть необходимость в глобальных переменных, которые будут «видны» в любом месте шаблона — можно использовать метод setGlobal() вместо set().
Пример 6.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
Фактически на этом простом механизме попеременных итераций вложенных контекстов реализуется абсолютно любая логика даже в одном единственном шаблоне.
В-общем, функционал контекстов достаточно мощный для того, что бы использовать шаблонный движок для сколь угодно сложных проектов.
Blitz поддерживает 4 типа:
Типы аналогичны типам PHP, за исключением того, что нет разницы — заключена строка в двойные или одинарные кавычки.
Возможность включать в шаблон пользовательские методы - самая интересная с точки зрения организации хорошего и удобно читаемого кода. До сих пор в примерах использовался стандартный класс Blitz, никакими новыми методами не обладающий. Однако если создать объект класса-наследника Blitz, который предоставляет некоторый метод my_test, в шаблоне можно использовать вызов этого метода ровно с таким же названием.
Пример 8.1. Вызов пользовательского метода
пример вызова пользовательского метода: {{ my_test }}<?
class BlitzTemplate extends Blitz {
function my_test() {
return 'user method called ('.__CLASS__.','.__LINE__.')';
}
}
$T = new BlitzTemplate('tpl');
echo $T->parse();
?>пример вызова пользовательского метода: user method called (blitztemplate,5)
Все, что возвращает пользовательский метод, будет конвертировано в строку и подставлено вместо вызова. Если вызов метода в шаблоне есть, но самого метода нет — будет подставлена пустая строка. Вообще, действует обычное правило: никаких исходных вызовов никогда не присутствует в конечном результате, независимо от существования переменной, метода и проч.
Внутри пользовательского метода также можно включать другие шаблоны. Конечно, никто не запрещает вам написать что-нибудь вроде:
class BlitzTemplate extends Blitz {
var $data;
var $TItem;
function BlitzTemplate($t,$titem) {
parent::Blitz($t);
$TItem = new Blitz($titem);
}
function set_data() {
// some code
}
function my_test() {
$result = '';
foreach ($this->data as $i_data) {
$result .= $TItem->parse($i_data);
}
return $result;
}
}
$T = new BlitzTemplate('main.tpl','item.tpl');
// $bla_bla = ...
$T->set_data($blabla);
echo $T->parse();
Этот метод будет работать, но не очень хорош по двум причинам. Во-первых, $TItem является совершенно отдельным объектом, никак не связанным с $T. Blitzу несколько сложнее переключаться с одного объекта на другой, нежели выполнять все операции через один и тот же объект. Во-вторых, $TItem не будет наследовать установленные переменные из $T, их при необходимости нужно будет протягивать самостоятельно, а также внутри $TItem нельзя использовать методы $T. Поэтому более правильным будет использование встроенного метода include().
Начиная с версии 0.3 в Blitz поддерживается передача параметров из шаблона в пользовательский метод.
Пример 8.2. Передача параметров из шаблона в пользовательский метод
calling template with arguments: {{ my_test(134,$x,"hello,world!",$dummy) }}<?
class BlitzTemplate extends Blitz {
var $titem;
function BlitzTemplate($t) {
parent::Blitz($t);
$this->set(array('x' => 1234));
}
function my_test($p1,$p2,$p3,$p4) {
$result = 'user method called ('.__CLASS__.','.__LINE__.')'."\n";
$result .= 'parameters are:'."\n";
$result .= '1:'.var_export($p1,TRUE)."\n";
$result .= '2:'.var_export($p2,TRUE)."\n";
$result .= '3:'.var_export($p3,TRUE)."\n";
$result .= '4:'.var_export($p4,TRUE)."\n";
return $result;
}
}
$T = new BlitzTemplate('tpl');
echo $T->parse();
?>calling template with arguments: user method called (blitztemplate,12) parameters are: 1:134 2:1234 3:'hello,world!' 4:NULL
Переменные представлены знаком blitz.var_prefix с последующим именем переменной. Имя переменной чувствительно к регистру.
Пример 9.1. Переменные
Это некоторый тест для двух переменных: {{ $a }} и {{ $b }}, номер итерации: {{ $i }}<?
$T = new Blitz('tpl');
$i = 0;
$i_max = 10;
for ($i = 0; $i<$i_max; $i++) {
echo $T->parse(
array(
'a' => 'var_'.(2*$i),
'b' => 'var_'.(2*$i+1),
'i' => $i
)
);
}
?>Это некоторый тест для двух переменных: var_0 и var_1, номер итерации: 0 Это некоторый тест для двух переменных: var_2 и var_3, номер итерации: 1 Это некоторый тест для двух переменных: var_4 и var_5, номер итерации: 2 Это некоторый тест для двух переменных: var_6 и var_7, номер итерации: 3 Это некоторый тест для двух переменных: var_8 и var_9, номер итерации: 4 Это некоторый тест для двух переменных: var_10 и var_11, номер итерации: 5 Это некоторый тест для двух переменных: var_12 и var_13, номер итерации: 6 Это некоторый тест для двух переменных: var_14 и var_15, номер итерации: 7 Это некоторый тест для двух переменных: var_16 и var_17, номер итерации: 8 Это некоторый тест для двух переменных: var_18 и var_19, номер итерации: 9
Содержание
Содержание
(blitz ≥ 0.4.10)
clean — очистить переменные и итерации контекста$Tpl->clean($context_path) очищает переменные и итерации контекста. Параметр $context_path по умолчанию равен корню (/) — $Tpl->clean() без параметров очистит все переменные и итерации шаблона.
Второй параметр управляет генерацией предупреждения PHP когда очищаемая итерация не найдена, по умолчанию true.
Пример 8. clean
================================
context cleaning ({{ $var }})
================================
<!-- BEGIN a -->context (a)
{{ $va }}
<!-- BEGIN b -->context (b)
{{ $vb }}
<!-- END b -->
<!-- END --><?php
$T = new Blitz('tpl');
$T->set(array('var' => 'Hello, World!'));
$T->block('/a', array('va' => 'va_value'));
$T->block('/a/b', array('vb' => 'vb_value'));
echo $T->parse();
$T->clean('/a/b');
echo $T->parse();
$T->clean('/a');
echo $T->parse();
$T->block('/a', array('va' => 'va_value_new'));
$T->iterate('/a/b');
echo $T->parse();
$T->clean();
echo $T->parse();
?>================================
context cleaning (Hello, World!)
================================
context (a)
va_value
context (b)
vb_value
================================
context cleaning (Hello, World!)
================================
context (a)
va_value
================================
context cleaning (Hello, World!)
================================
================================
context cleaning (Hello, World!)
================================
context (a)
va_value_new
context (b)
================================
context cleaning ()
================================
(blitz ≥ 0.4)
context — установить контекстПример 9. context
{{BEGIN user}}
{{BEGIN hello}}
Hello, user!
{{END}}
{{BEGIN goodbye}}
Goodbye, user!
{{END}}
{{END}}
{{BEGIN world}}
Hello, world!
{{END}}<?php
$Template = new Blitz('tpl');
$Template->context('user');
$Template->block('hello');
$Template->block('goodbye');
$Template->block('../world');
echo $Template->parse();
?>Hello, user! Goodbye, user! Hello, world!
См. также block().
(blitz ≥ 0.4)
dumpIterations — дамп итерацийПсевдоним метода — dump_iterations.
Пример 10. dumpIterations
{{BEGIN counter}}
{{$i}},
{{END}}<?php
$Template = new Blitz('tpl');
for ($i = 0; $i < 3; $i++)
{
$Template->block('counter', array('i' => $i));
}
$Template->dumpIterations();
?>ITERATION DUMP (4 parts)
(1) iterations:
array(1) {
[0]=>
array(1) {
["counter"]=>
array(3) {
[0]=>
array(1) {
["i"]=>
int(0)
}
[1]=>
array(1) {
["i"]=>
int(1)
}
[2]=>
array(1) {
["i"]=>
int(2)
}
}
}
}
(2) current path is: /
(3) current node data (current_iteration_parent) is:
array(1) {
[0]=>
array(1) {
["counter"]=>
array(3) {
[0]=>
array(1) {
["i"]=>
int(0)
}
[1]=>
array(1) {
["i"]=>
int(1)
}
[2]=>
array(1) {
["i"]=>
int(2)
}
}
}
}
(4) current node item data (current_iteration) is:
array(1) {
["counter"]=>
array(3) {
[0]=>
array(1) {
["i"]=>
int(0)
}
[1]=>
array(1) {
["i"]=>
int(1)
}
[2]=>
array(1) {
["i"]=>
int(2)
}
}
}См. также dumpStruct().
(blitz ≥ 0.4)
dumpStruct — дамп структурыПсевдоним метода — dump_struct.
Пример 11. dumpStruct
{{BEGIN counter}}
{{$i}},
{{END}}<?php
$Template = new Blitz('tpl');
for ($i = 0; $i < 3; $i++)
{
$Template->block('context', array('i' => $i));
}
$Template->dumpStruct();
?>== TREE STRUCT (2 nodes): ^-begin[22] (0(17), 32(27)); ARGS(1): counter(0); CHILDREN(1): ^-i[1] (19(0), 23(0)); == PLAIN STRUCT (2 nodes): begin[22] (0(17), 32(27)); ARGS(1): counter(0); CHILDREN(1): i[1] (19(0), 23(0));
См. также dumpIterations().
(blitz ≥ 0.4)
fetch — использовать контент одного шаблона при работе с другим шаблоном или тело одного контекста в одном шаблоне внутри другогоПример 12. fetch
{{ BEGIN online }} online! {{ END }}
{{ BEGIN offline }} was online {{ $n }} {{ BEGIN h }}hours{{ END }}{{ BEGIN d }}days{{ END }}{{ BEGIN m }}months{{ END }} ago {{ END }}
{{ BEGIN away }} away... {{ END }}<?
$T = new Blitz('tpl');
// online
echo $T->fetch('online')."\n";
// away
echo $T->fetch('away')."\n";
$T->context('offline');
// 15 days ago
$T->iterate('d');
echo $T->fetch('offline', array('n' => 15))."\n";
// 2 months ago
$T->iterate('m');
echo $T->fetch('offline', array('n' => 2))."\n";
?>online! away... was online 15 days ago was online 2 months ago
Метод fetch получает результат исполнения последней итерации контекста.
iterate(), чтобы очистить извлеченные итерации. С версии 0.4.2 каждый вызов fetch автоматически очищает предыдущие итерации контекста.
(blitz ≥ 0.1)
include — подключение другого шаблонаПример 14. include
<?php
class View extends Blitz {
var $news = array();
function View($tmpl_name) {
return parent::Blitz($tmpl_name);
}
function set_news($data) {
$this->news = $data;
}
function list_news() {
$result = '';
foreach($this->news as $i_news) {
$result .= $this->include('news_list_item.tpl', $i_news);
}
return $result;
}
}
?>Метод list_news возвращает результат исполнения шаблона news_list_item.tpl, передавая данные новости как глобальные переменные в подключаемый шаблон. В текущей версии (0.4.3) include не поддерживает итерацию контекстов — все контексты подключаемого шаблона будут скрыты. Нет возможности передать составные итеративные данные — только одномерный ассоциативный массив глобальных переменных. Если необходимо подключить сложные шаблоны с вложенными контекстами, используйте fetch().
(blitz ≥ 0.4)
iterate — итерировать контекстПример 15. iterate
{{BEGIN hello}}
Hello, user!
{{END}}
{{BEGIN goodbye}}
Goodbye, user!
{{END}}<?php
$Template = new Blitz('tpl');
$Template->iterate('hello');
$Template->context('goodbye');
$Template->iterate();
echo $Template->parse();
?>Hello, user! Goodbye, user!
(blitz ≥ 0.1)
parse — разобрать шаблонПример 17. parse без установки глобальных переменных
Hello, world!
<?php
$Template = new Blitz('tpl');
echo $Template->parse();
?>Hello, world!
Пример 18. parse с установкой глобальных переменных
Hello, {{$object}}!<?php
$Template = new Blitz('tpl');
echo $Template->parse(array('object' => 'world'));
?>Hello, world!
(blitz ≥ 0.1)
set — установить переменныеПример 19. set
Hello, {{$object}}!<?php
$Template = new Blitz('tpl');
$Template->set(array('object' => 'world'));
echo $Template->parse();
?>Hello, world!
Пример 20. set как «быстрый» способ установить целый массив итераций
<projects>
{{BEGIN project}}
<project label="{{$url}}" data="{{$id}}"/>
{{END}}
</projects><?php
$data = array (
'project' => array(
0 => array('url' => 'a', 'id' => '1'),
1 => array('url' => 'b', 'id' => '2'),
2 => array('url' => 'c', 'id' => '3'),
)
);
$Template = new Blitz('tpl');
$Template->set($data);
echo $Template->parse();
?><projects> <project label="a" data="1"/> <project label="b" data="2"/> <project label="c" data="3"/> </projects>
Массив $data описывает 3 итерации контекста project с их локальными переменными url и id. Структура данных может быть сколь угодно сложной, но при соблюдении следующего правила: числовые ключи для итераций контекста, строчные для имен контекстов и переменных. Таким образом можно не вызывать context/iterate/set, а сначала «приготовить» такую вот структуру данных, а потом одним махом засадить эти итерации в шаблон — иногда это удобно (к примеру, вместе с PDO::fetchAll(PDO::FETCH_ASSOC)) и вообще говоря, это работает очень быстро (blitz ctx arrays в benchmarks).
См. также setGlobal(), block().
(blitz ≥ 0.4)
setGlobal — установить глобальные переменныеПсевдоним метода — set_global.
Пример 21. setGlobal
I am {{$local}} variable.
I am {{$global}} variable.
{{BEGIN context}}
I am {{$local}} variable.
I am {{$global}} variable.
{{END}}<?php
$Template = new Blitz('tpl');
$Template->set(array('local' => 'local (root)'));
$Template->setGlobal(array('global' => 'global'));
$Template->block('context', array('local' => 'local (context)'));
echo $Template->parse();
?>I am local (root) variable. I am global variable. I am local (context) variable. I am global variable.
См. также set().
Содержание
(blitz ≥ 0.4.11)
date — форматировать дату/времяformat задается так же как и для функции PHP strftime.
Если time — число, то трактуется как метка времени UNIX, иначе как GNU формат даты.
Пример 22. date
{{ date("%d %m %Y %H:%M:%S", $time_num) }}
{{ date("%d %m %Y %H:%M:%S", $time_str) }}<?php
$T = new Blitz('tpl');
$time_num = mktime(11, 22, 33, 7, 22, 1976);
$time_str = '1976-07-22 01:02:03';
$T->set(array(
'time_num' => $time_num,
'time_str' => $time_str
));
echo $T->parse();
?>22 07 1976 12:22:33 22 07 1976 05:02:03
(blitz ≥ 0.4.4)
escape — преобразовать специальные символы в сущности HTMLВ режиме по умолчанию, ENT_QUOTES, преобразуются и двойные, и одиночные кавычки, а в режиме ENT_COMPAT только двойные кавычки.
Пример 23. escape
{{escape($a)}}
{{escape($b)}}
{{escape($c, 'ENT_COMPAT')}}<?php
$T = new Blitz('tpl');
$T->set(
array(
'a' => "this is 'a' \"test\"",
'b' => '<a href="null">',
'c' => '<>@#$%^&*()_=\'"'
)
);
echo $T->parse();
?>this is 'a' "test" <a href="null"> <>@#$%^&*()_='"
(blitz ≥ 0.1)
if — отобразить в зависимости от истинности предиката либо один аргумент, либо другойПример 24. if
{{ $num }}. {{ $name }} {{ if($rip,'[R.I.P.]') }}<?
$T = new Blitz('tpl');
$character = array(
array(1,'The Dude',0),
array(2,'Walter Sobchak',0),
array(3,'Donny',1),
array(4,'Maude Lebowski',0),
array(5,'The Big Lebowski',0),
array(6,'Brandt',0),
array(7,'Jesus Quintana',0),
);
foreach ($character as $i => $data) {
echo $T->parse(
array(
'num' => $data[0],
'name' => $data[1],
'rip' => $data[2]
)
);
}
?>1. The Dude 2. Walter Sobchak 3. Donny [R.I.P.] 4. Maude Lebowski 5. The Big Lebowski 6. Brandt 7. Jesus Quintana
В данном примере использована укороченная форма if.
(blitz ≥ 0.1)
include — подключение другого шаблонаПример 25. include
1.tpl
В чем {{ include('2.tpl') }} жизни?2.tpl
смысл
<?php
$Template = new Blitz('1.tpl');
echo $Template->parse();
?>В чем смысл жизни?
Политика области видимости переменных очень проста: глобальные переменные видны в подключенном шаблоне, а локальные нет.