|
Документация |
Шаблонизатор Separate Версия 1.6 (03.03.2018, PHP7) |
Что такое Separate?
Separate - это объектно-ориентированный шаблонизатор для PHP7.
С помощью Separate можно отделить бизнес-логику (например, загрузку информации из базы данных)
от уровня представления (HTML кода) и тем самым создать чистый и хорошо структурированный
исходный код.
Архитектура шаблонизатора Separate
Основные свойства архитектуры
В процессе разработки большое значение уделялось динамическому расширению функции, как, например, форматированию значений
с использованием Value Formatter.
В целом, в архитектуру были интегрированы следующие свойства:
- Минимальные функциональные ограничения (возможность расширения посредством собственной функциональности).
- Простой API (например, для использования требуется только Template.php файл).
- Независимость от других библиотек (например, Pear).
Структура приложения на базе Separate
Приложения, которые основаны на Separate, состоят из уровня представления
(Presentation Layer) и бизнес-логики.
Уровень представления содержит HTML код,
переменные шаблона и другие конструкты шаблонизатора Separate.
В бизнес-логике осуществляются различные вычисления, а затем сгенерированные
данные передаются соответствующим переменным шаблона.
Верхний рисунок изображает бизнес-логику и уровень представления (Presentation Layer),
которые обрабатываются шаблонизатором Separate.
В качестве конечного результата шаблонизатор генерирует HTML код.
Интеграция в собственный проект
Для Separate требуется PHP7 или выше.
Чтобы использовать Separate, нужно подключить Template класс.
require_once './Template.php';
|
Затем нужно загрузить файл шаблона. Для этого используется метод \separate\Template::initialize('...') .
$t = \separate\Template::initialize('./index.htm');
|
После успешной загрузки могут выполняться основные
действия, как, например, присваивание значений к переменным шаблона.
$t->assign('MY_VARIABLE', 'my value');
|
Чтобы в завершении сгенерировать HTML код,
используется метод \separate\Template::display().
\separate\Template::display();
|
Следующий код содержит все выше описанные шаги имплементации.
<?php
require_once './Template.php';
$t = \separate\Template::initialize('./index.htm');
$t->assign('MY_VARIABLE', 'my value');
\separate\Template::display();
|
Переменные шаблона
Для каждой динамической информационной единицы
в шаблоне указывается переменная.
В процессе генерации страницы шаблонизатор заменяет эти переменные информацией.
Синтаксис выглядит следующим образом:
Динамические блоки
Динамическими блоками вы можете разделить исходный код на разделы,
которые во время выполнения могут повторяться любое количество раз.
Данная возможность предназначена, например, для генерации таблицы с динамическим количеством строк.
Синтаксис выглядит следующим образом:
<!-- BEGIN <название блока> -->
HTML код...
<!-- END <название блока> -->
|
|
В PHP коде каждый блок является Template объектом.
Методом Template->fetch(...) создается новый блок.
После манипуляции блок передается методом Template->assign(...) обратно исходному Template объекту.
В зависимости от количества данных этот процесс необходимо повторить определенное количество раз.
Ниже приведенный пример демонстрирует простую реализацию динамических блоков.
|
PHP код:
<?php
require_once './Template.php';
$rootTemplate = \separate\Template::initialize('./index.htm');
for($row = 1; $row <= 3; $row++)
{
//fetch row block from root template
$rowBlock = $rootTemplate->fetch('row');
for($column = 1; $column <= 3; $column++)
{
//fetch column block from row block
$columnBlock = $rowBlock->fetch('column');
$columnBlock->assign('ROW_NUMBER', $row);
$columnBlock->assign('COLUMN_NUMBER', $column);
//assign modified column block back to row block
$rowBlock->assign('column', $columnBlock);
}
//assign modified row block back to root template
$rootTemplate->assign('row', $rowBlock);
}
\separate\Template::display();
?>
|
Исходный код шаблона (index.htm):
<html>
<body>
<table>
<!-- BEGIN row -->
<tr>
<!-- BEGIN column -->
<td>Row: ${ROW_NUMBER} Column: ${COLUMN_NUMBER}</td>
<!-- END column -->
</tr>
<!-- END row -->
</table>
</body>
</html>
|
Как вы видите, в блоках могут также определяться дальнейшие под-блоки.
Сгенерированный HTML код выглядит следующим образом:
<html>
<body>
<table>
<tr>
<td>Row: 1 Column: 1</td>
<td>Row: 1 Column: 2</td>
<td>Row: 1 Column: 3</td>
</tr>
<tr>
<td>Row: 2 Column: 1</td>
<td>Row: 2 Column: 2</td>
<td>Row: 2 Column: 3</td>
</tr>
<tr>
<td>Row: 3 Column: 1</td>
<td>Row: 3 Column: 2</td>
<td>Row: 3 Column: 3</td>
</tr>
</table>
</body>
</html>
|
Присвоение значений
Чтобы присвоить шаблонным переменным значения, в PHP коде используются определенные методы.
Существуют три вида таких методов:
1. Простое присвоение значений
Видимость значений, которые были присвоены методом Template->assign(...),
ограничивается текущим блоком
или корневым уровнем шаблона. Переменные, которые находятся в других блоках, при этом игнорируются.
$t->assign('MY_VARIABLE', 'my value');
|
2. Блок-релевантное присвоение значений
Этим методом можно присвоить значение к переменной, которая находится в определенном блоке (включая дальнейшие под-блоки).
Переменные, находящиеся в других блоках, игнорируются.
$t->assignForBlock('MY_BLOCK_VARIABLE', 'my block value');
|
3. Глобальное присвоение значений
С методом Template->assignForGlobal(...) можно присвоить значения ко всем переменным, независимо от того, в каком блоке они находятся.
Использование данного метода имеет смысл в основном только для тех переменных, которые часто встречаются в разных
областях исходного кода.
$t->assignForGlobal('MY_GLOBAL_VARIABLE', 'my global value');
|
Форматирование значений
По умолчанию все значения, которые были присвоены переменным шаблона, представляются в HTML коде без изменений.
Но иногда бывают ситуации, когда необходимо изменить значение.
Например, если на странице представлен
текст, содержащий управляющие символы HTML (<, >, &, ...).
Эти символы необходимо конвертировать при генерировании страницы.
Чтобы сделать весь процесс максимально удобным и
динамичным, Separate поддерживает так называемые Value Formatter.
Value Formatter содержит определенные инструкции для форматирования информации.
Значения, которые передаются переменной с использованием Value Formatter, отображаются в
конвертированном виде. Синтаксис переменной с Value Formatter выглядит следующим образом:
${(<название форматера>)<название переменной>}
|
Следующий пример показывает реализацию простого форматирования с использованием Value Formatter, которое
конвертирует Unix Timestamp значение в читабельное обозначение даты или времени.
PHP код:
<?php
require_once './Template.php';
require_once './formatter/DateFormatter.php';
require_once './formatter/TimeFormatter.php';
$t = \separate\Template::initialize('./index.htm');
$t->assign('UNIX_TIMESTAMP', time());
\separate\Template::display();
?>
|
Исходныи код шаблона (index.htm):
<html>
<body>
Timestamp: ${UNIX_TIMESTAMP}<br>
Date: ${(Date)UNIX_TIMESTAMP}<br>
Time: ${(Time)UNIX_TIMESTAMP}
</body>
</html>
|
Сгенерированный HTML код выглядит следующим образом:
<html>
<body>
Timestamp: 1520104433<br>
Date: 03.03.2018<br>
Time: 19:13
</body>
</html>
|
Форматирование значений по умолчанию
С помощью метода Template::setDefaultFormatter(...) можно установить
Value Formatter, который будет по умолчанию применяться во всех переменных шаблона.
\separate\Template::setDefaultFormatter(new TextFormatter());
|
Уже существующие Value Formatter классы
В Separate уже включенo несколько Value Formatter классов.
Класс |
Название форматера |
Описание |
DateFormatter |
Date |
Конвертирует Unix Timestamp в читабельную дату, например, 03.03.2018 |
TimeFormatter |
Time |
Конвертирует Unix Timestamp в читабельное обозначение времени, например, 19:13 |
DateTimeFormatter |
DateTime |
Конвертирует Unix Timestamp в читабельную дату с дополнительным обозначением времени, например, 03.03.2018 19:13 |
TextFormatter |
Text |
Заменяет все управляющие символы HTML (например, <, > или &) предусмотренными для этого символами (например, <, > или &). |
UrlFormatter |
Url |
Создает URL-совместимую строку, которая в первую очередь предназначена для гиперссылок. |
HashFormatter |
Hash |
Используется в IF-условии для сравнения двух неизвестных строк. |
IsEmptyFormatter |
IsEmpty |
Используется в IF-условии
для того, чтобы проверить, является ли переменная пустой.
|
Собственные Value Formatter классы
Наряду с уже существующими Value Formatter классами можно также создавать собственные.
Для этого необходимо создать класс который наследует от класса \separate\ValueFormatter и
имплементирует \separate\ValueFormatter->formatValue(...) метод.
При наименовании собственного Value Formatter класса нужно придерживаться определенным правилам нотации.
Название класса начинается с названия форматера, который используется с переменными,
и всегда заканчивается словом "Formatter".
<название форматера>Formatter
|
Следующий пример с собственным Value Formatter классом конвертирует переданное значение в верхний регистр.
PHP код:
<?php
require_once './Template.php';
class ToUpperFormatter extends \separate\ValueFormatter
{
public function formatValue(string $value) : string
{
return strtoupper($value);
}
}
$t = \separate\Template::initialize('./index.htm');
$t->assign('MY_VARIABLE', 'my value');
\separate\Template::display();
?>
|
Код шаблона (index.htm):
<html>
<body>
${(ToUpper)MY_VARIABLE}
</body>
</html>
|
Сгенерированный HTML код выглядит следующим образом:
<html>
<body>
MY VALUE
</body>
</html>
|
Переменные без возможности форматирования
Иногда важно чтобы HTML код генерировался с максимально возможной скоростью.
Для этого требования существует специальный вид переменных, которые в процессе генерации
обрабатываются очень быстро, но не поддерживают форматирование значений.
В коде шаблона переменные такого рода начинаются с символа #:
В PHP коде для этого должны использоваться специальные Assign-методы.
Эти методы идентичны с обычными Assign-методами,
но начинаются с символа х.
$t->xassign('MY_VARIABLE', 'my value');
$t->xassignForBlock('MY_BLOCK_VARIABLE', 'my block value');
$t->xassignForGlobal('MY_GLOBAL_VARIABLE', 'my global value');
|
Интеграция дополнительных файлов в шаблон
В основной шаблонный код можно интегрировать код из других файлов.
Синтаксис команды:
<!-- INCLUDE <название файла> -->
|
Следующий пример показывает реализацию интеграции дополнительных файлов в шаблон.
Header-файл (header.htm):
Footer-файл (footer.htm):
Код основного шаблона (index.htm):
<!-- INCLUDE header.htm -->
<p>Hallo</p>
<!-- INCLUDE footer.htm -->
|
IF-условия
Иногда требуется расположить IF-условия на уровне представления.
В Separate это возможно. Синтаксис выглядит следующим образом:
<!-- IF <условие 1> -->
HTML код...
<!-- ELSE IF <условие 2> -->
HTML код...
<!-- ELSE -->
HTML код...
<!-- END IF -->
|
Условие может состоять из нескольких переменных.
Также можно использовать все операторы сравнения доступные в PHP.
Далее иллюстрируется простая реализация IF-условия.
PHP код:
<?php
require_once './Template.php';
$t = \separate\Template::initialize('./index.htm');
$t->assign('MY_VARIABLE', 'hallo');
\separate\Template::display();
?>
|
Код шаблона (index.htm):
<html>
<body>
<!-- IF '${MY_VARIABLE}' == 'hallo' -->
The value of MY_VARIABLE is 'hallo'
<!-- ELSE -->
The value of MY_VARIABLE is '${MY_VARIABLE}'
<!-- END IF -->
</body>
</html>
|
Особенности сравнения значений
Для обеспечения максимальной скорости, шаблонизатором не
осуществляются определенные проверки значений.
Поэтому разработчику необходимо самостоятельно обращать внимание на некоторые особенности.
Чтобы сравнить два неизвестныx значения, нужно
использовать Hash-форматер, который преобразует значения в хеш-строки.
<!-- IF '${(Hash)MY_VARIABLE_A}' == '${(Hash)MY_VARIABLE_B}' -->
...
<!-- END IF -->
|
Чтобы проверить, содержит ли переменная пустую строку, нужно использовать
IsEmpty форматер. Если переменная содержит пустую строку, значение конвертируется
в "TRUE". В противном случае значение конвертируется в "FALSE".
<!-- IF '${(IsEmpty)MY_VARIABLE}' == 'TRUE' -->
...
<!-- END IF -->
|
Чтобы упростить логические сравнения, можно воспользоваться методом
\separate\Template::booleanToString(...). Он преобразует логическое значение в строковое "TRUE" или "FALSE".
PHP код:
$t->xassign('LOGGED_IN_FLAG', \separate\Template::booleanToString(...));
|
Код шаблона:
<!-- IF '#{LOGGED_IN_FLAG}' == 'TRUE' -->
...
<!-- END IF -->
|
Параметры шаблона
С помощью параметров шаблона можно установить любые настройки в самом коде шаблона.
Эти параметры потом доступны в PHP коде. Для чего это нужно? Вот пример из практики:
Иногда веб-приложения имеют несколько интерфейсов.
Например, когда наряду с обычным интерфейсом также предоставляется интерфейс для мобильных устройств.
В таком случае для
одной и той же бизнес-логики разрабатываются два различных шаблона – один для
стандартного интерфейса, другой– для мобильных устройств.
Предположим, что у нас
есть динамически сгенерированная таблица с множеством данных, которые в свою
очередь распределены по многим страницам.
В стандартном интерфейсе на
каждой странице будут показываться 100 строк.
В интерфейсе для
мобильных устройств на странице можно показать максимально 10 строк
записи, большее количество там просто не поместится.
Чтобы реализовать это, не прибегая к каким-либо изменениям в PHP коде, и разработаны так называемые параметры шаблона.
Синтаксис:
<!-- PARAMETER <название параметра> '<значение параметра>' -->
|
Пример:
<!-- PARAMETER NUMBER_OF_ROWS '100' -->
|
В PHP коде все доступные параметры можно прочитать методом Template::getParameters().
Кроме того, методом Template::setParameterValue(...) во время выполнения
можно установить новые параметры или поменять уже существующие.
Комментарии в шаблоне
Всем известно, что в HTML есть комментарии, которые выглядят следующим образом:
<!-- HTML комментарий... -->
|
У таких комментариев существует два недостатка:
во-первых, они
отсылаются клиенту и создают ненужный трафик.
Во-вторых, эти комментарии
видны в HTML коде.
По этой причине Separate
позволяет создавать специальные комментарии в шаблоне.
Эти комментарии удаляются в сгенерированном HTML коде, и поэтому не передаются клиенту.
Синтаксис выглядит следующим образом:
<!--- Шаблонный комментарий... --->
|
Рекомендации
Наименование многих компонентов исходного кода предоставляется самому программисту.
Тем не менее, рекомендуется использовать заранее постановленные правила.
Наименование Template переменных в PHP коде
Рекомендуется сохранять все Template объекты в одном массиве (например, $t).
Название блока при этом просто передается в виде ключа.
В нижеприведенном примере $t['.'] содержит
корневой Template объект, а $t['block']['.'] и $t['block']['sub_block']['.'] соответствующие Template объекты блоков.
$t['.'] = \separate\Template::initialize('./index.htm');
for(...)
{
$t['block']['.'] = $t['.']->fetch('block');
for(...)
{
$t['block']['sub_block']['.'] = $t['block']['.']->fetch('sub_block');
//...
$t['block']['.']->assign('sub_block', $t['block']['sub_block']['.']);
}
$t['.']->assign('block', $t['block']['.']);
}
\separate\Template::display();
|
Наименование переменных шаблона в больших проектах
В больших проектах может случиться так, что у одного названия переменной существует несколько
специальных значений.
Например, в многоязычном приложении переменная NAME может
использоваться как для имени пользователя (например, "Вася Пупкин") так и для языковых фраз (например, "Имя").
Чтобы избежать таких конфликтов, рекомендуется определить префикс для каждой смысловой области.
#{LANGUAGE.NAME}: ${VALUE.NAME}
|
В выше приведенном примере все переменные для фраз на актуальном
языке начинаются со слова LANGUAGE, а все переменные для динамических значений – со слова VALUE.
Еще одно преимущество заключается в том, что при каждой генерации страницы можно
автоматически присваивать значения переменным с префиксом LANGUAGE.
Метод Template->getVariableNames() используется для того, чтобы определить все LANGUAGE переменные.
После этого переменным присваиваются значения методом Template->xassignForGlobal(...).
Лицензия
Шаблонизатор Separate разработан Эдуардом Судником и является фреймворком с открытым
исходным кодом для PHP, который предоставляется в распоряжение посредством
лицензии MIT.
|
|