Pull to refresh

Введение в шаблонизатор Blitz

Reading time5 min
Views10K
Original author: Алексей Рыбак
Из документации о Blitz: Чрезвычайно быстрый и мощный шаблонизатор для очень больших интернет-проектов.

Приведу несколько фактов:
  1. Это шаблонизатор используемый Хабром;
  2. Этот шаблонизатор используется на высоко-нагруженных проектах, он написан на C, подключается как расширение PHP;
  3. Его скорость сопоставима с самим php (бенчмарк под катом);
  4. Верстальщики будт счастливы, так как в шаблонах нет логики приложения, нет циклов, ветвлений и т.д.;
  5. Один из его авторов Алексей Рыбак fisher.




Бенчмарк шаблонизаторов

Blitz — это блочный шаблонизатор, что принципиально отличает его от Smarty и подобных.
Smarty по сравнению с Blitz — язык программирования.

Синтаксис шаблонов Blitz основан на 3х конструкциях:
  1. блоки (они же контексты): {{BEGIN blockName}}содержимое блока{{END}}
  2. переменные: {{$var}}
  3. вызовы функций {{myFunc($params)}}

Циклы, условыне операторы и другой «богатый» синтаксис отсутствует. Это гарантирует разделение логики
приложения от логики представления. Как следствие, шаблоны с ростом проекта не превращаются в кашу.

С точки зрения организации кода, компонент View (MVC) можно условно разделить на две части:
  1. шаблон (HTML-файл с Blitz-тегам);
  2. контроллер шаблона — это объект Blitz управляющий обработкой шаблона (не путать с контроллером веб-приложения).


Контроллер шаблона несет всю избыточную для шаблона логику с которой программисты справляются гораздо
эффективнее чем верстальщики.

Несколько примеров:


1. По традиции: Hello, world!


Шаблон template.tpl:
 
    Hello, {{ $name }}!


скрипт:
  
    $template = new Blitz('template.tpl');
    echo $template->parse(array('name' => 'world'));


2. Шаблон можно загрузить не только из файла:

Для экспериментов с Blitz вы можете загрузить
шаблон прямо в коде скрипта из переменной:
  
    $template = new Blitz();
    $template->load('Hello, {{$name}}!');
    echo $template->parse(array('name' => 'world'));


3. Блоки (контексты):

Блок это часть шаблона, которая может быть отображена при необходимости:
    hello {{  BEGIN block }} {{ $name }} {{ END }}

По умолчанию, этот шаблон выводит строку «hello », блок будет скрыт.

Следующий код выведет блок один раз:
  
    $template = new Blitz('some.tpl');
    $template->block('/block', array('name' => 'Dude'));
    echo $template->parse();

Результат
"hello  Dude ".

Синоним Блока — контекст. Вывод блока называется итерацией.

Для наглядности можно указать название блока после оператора END:
{{ END block }}.
4. Вывод блока несколько раз (списки или циклы):

Каждый блок может быть «итерирован» несколько раз для вывода списков (аналог циклов в Smarty), код контроллера шаблона:
    foreach (array('Dude', 'Sobchak', 'Donny') as $i_name) {
      $template->block('/block', array('name' => $i_name);
    }

Выполнив данный код для шаблона из предыдущего примера, мы увидим:
    "Hello  Dude  Donny  Sobchak "

5. Условия

Теперь попробуем вывести тот же список, но разделенный запятыми.
Это можно сделать двумя способами: использовать блок или оператор if.

Для начала используем блок:
  hello {{ BEGIN block }}{{ BEGIN comma }},{{ END }} {{ $name }} {{ END }}


и проитерируем его в цикле:
    $need_comma = FALSE;
    foreach (array('Dude', 'Sobchak', 'Donny') as $i_name) {
       if ($need_comma) {
           $template->block('/block/comma');
       } else {
           $need_comma = TRUE;
       }
       $template->block('/block', array('name' => $i_name);
    }


По мне, так выглядит не слишком изящно. В таких простых случаях уместнее использовать оператор if:

    hello {{ BEGIN block }}{{ if($_first,'',',') }} {{ $name }} {{ END }}.


В Blitz для блоков есть предустановленные переменные: $_first (первая итерация),
$_last (последняя итерация), $_total (общее кол-во), $_num, $_even, $_odd.
По названием легко догататься о назначении. Также можно определить
свои переменные из контроллера шаблона.

Еще пара примеров if:
    {{ if(TRUE,'2+2=4','2+2=5'); }}
    {{ if($a,"b",$c); }}

6. Использование контекстов и итераций

Вместо блока можно использовать комбинацию трех низкоуровневых методов:
context, set и iterate. Метод context принимает один параметр — полный или относительный
путь, все дальнейшие set-ы и относительные пути будут использовать этот путь по умолчанию:
    $template->context('/block');
    foreach (array('Dude', 'Sobchak', 'Donny') as $i_name) {
      $template->iterate();
      $template->set(array('name' => $i_name));
    }


Метод context работает как консольная команда cd;
метод iterate «выводит» блок.

Использования block проще, но во многих случаях Вам понадобятся
низко-уровневые операции с контекстом и итерированием.

7. Все является итерацией

Каждое состояние шаблона может быть описано определенной структурой данных.
Если добавить следующий код к предыдущему примеру:
    $data = $template->getIterations();

в $data будет следующая структура:
  array(
      0 => array(
          'block' => array(
               0 => array('name' => 'Dude'),
               1 => array('name' => 'Sobchak'),
               2 => array('name' => 'Donny')
           )
      ),
  )

Это внутреннее состояние шаблона перед вызовом метода parse.

Чтобы Вы не делали с шаблоном используя методы block, set, iterate, context
Blitz модифицирует данный массив. Когда вызывается метод parse — blitz рендерит
шаблон на основе этой структуры.

Попрактикуйтесь с разными вызовами и посмотрите, что будет в дампе, для быстрой отладки
вашего кода.

8. Все тоже самое, через массив:

    $data = array(
        0 => array(
            'block' => array(
                 0 => array('name' => 'Dude'),
                 1 => array('name' => 'Sobchak'),
                 2 => array('name' => 'Donny')
             )
        ),
    );

    $template = new Blitz('some.tpl');
    echo $template->parse($data);


some.tpl:
    {{ BEGIN block }}{{ if($_first,'',',') }} {{ $name }} {{ END }}


Тот же самый результат, что и в предыдущих примерах, но
без использования методов block/context/iterate.

9. Вложенные итерации

    $data = array(
        array(
            'who' => 'soldiers',
            'what' => array(
                0 => array(
                    'verb' => 'going',
                    'details' => array(
                        0 => array('item' => 'nowhere'),
                    )
                ),
                1 => array(
                    'verb' => 'blinded',
                    'details' => array(
                        0 => array('item' => 'by'),
                        1 => array('item' => 'their'),
                        2 => array('item' => 'faith')
                    )
                )
            )
        )
    );

    $template = new Blitz();
    $template->load('{{ $who }} {{ BEGIN what }}{{ $verb }} {{ BEGIN details }}{{ $item }} {{ END }}{{ END }}');
    $template->set($data);
    echo $template->parse();


результат исполнения:
    soldiers going nowhere blinded by their faith


Если вы поймете как это работает — вы полностью осознали
контексты и итерации.

10. Можно работать с частями шаблона

Иногда удобно взять часть шаблона (блок) независимо от всего шаблона:
Это можно сделать с помощью метода fetch:

some.tpl:
    {{ BEGIN hello }} hello, {{ $name }} {{ END }}
    {{ BEGIN bye }} bye, {{ $name }} {{ END }}


код:
    echo $template->fetch('/hello', array('name' => 'Lena')); // hello, Lena
    echo $template->fetch('/bye', array('name' => 'Sveta')); // bye, Sveta

11. Вызовы функций в шаблоне:

Следующий код
{{ my_test($a, "foo", 'bar', TRUE, 2005); }}
означает,
то что вы вызываете метод my_test с параметрами.

Функцию my_test добавим следующим образом:
  class View extends Blitz {
      function my_test($a) {
          return 'user method called ('.__CLASS__.','.__LINE__.'), a = '.$a;
      }
  }

  $template = new View();
  $template->load('user method call test: {{ my_test("test") }}');
  echo $template->parse();


Результат:
    user method call test: user method called (blitztemplate,5), a = test


В заключение:


Это введение было написано как вольный перевод туториала: Quck Geek Blitz Tutorial.
Оно лишь иллюстрирует основы использования этого шаблонизатора, за деталями
стоит обратиться к документации.

Ссылки


Сайт проекта Blitz: alexeyrybak.com/blitz/blitz_ru.html
Примеры шаблонов и бенчмарк: alexeyrybak.com/blitz/lebowski_bench.tar.gz
Tags:
Hubs:
+31
Comments147

Articles