
Панда-бир!
   
Профиль
Группа: Участник
Сообщений: 4795
Регистрация: 3.2.2003
Где: Бамбуковый лес
Репутация: нет Всего: 73
|
Всем желающим ознакомиться с чем то новым, предлогаю испытать написанный мною шаблонизатор. Возможности.1) Обработка и замена строк. 2) Обработка циклов в шаблоне (вложенные циклы не поддерживаются). 3) Обработка условий в шаблонах (вложенные условия не поддерживаются). Настройка, написания шаблонов и использование:- Служебные заголовки в шаблонах.
В классе существует несколько настроечных параметров которые определяют необходимо ли обработать тот или иной тип блоков в шаблоне. По умолчанию этим настройкам присвоены следующие значения: $ParseVariable = 1 // Выполнять поиск и замену строковых констант в шаблоне. $ParseCondition = 0 // Выполнять поиск и замену условий в шаблонах. $ParseLoop = 0 // Выполнять поиск и замену циклов в шаблоне.
Для того чтобы каждый раз не изменять код PHP для изменения данных параметров, предусмотрены заголовки в шаблонах, в которых можно устанавливать настроки класса по обработке блоков. Использование заголовков:
| Цитата | | <!--ud:header option = value--> |
Где option это имя настроечного параметра. Например
| Цитата | | <!--ud:header ParseLoop = 1--> | Разрешит обработку циклов в шаблоне. Примечание: так же можно настройки изменять внутри РНР скрипта. Например: | Цитата | | $TemplateClass->ParseLoop = 1; |
- Инициализация класса шаблонов.
| Цитата | <?php include('library/template.class.php'); // Подключение файла с классом шаблонов. $Template = implode('', file('templates/template.htm')); // Чтение файла с шаблоном. $TemplateClass = new UD_TemplateDocument($Template); // Инициализация класса шаблонов и загрузка документа. // ... ?> |
- Использование констант под замену в шаблонах.
Определение констант под замену оформляется следующим методом:
| Цитата | --- template.htm <p>Привет %session_user_name%, Вы были у нас последний раз %session_user_last_visit%</p> |
При этом чтобы назначить замену констант, необходим следующий код:
| Цитата | $TemplateClass->Assign('session_user_name', $_SESSION['user_name']); $TemplateClass->Assign('session_user_last_visit', $_SESSION['last_visit']); |
Есть еще один вариант назначения замены для шаблонных констант, который в некоторой степени упрощает определение большого количества переменных:
| Цитата | $TemplateClass->Assign( array( 'session_user_name', 'session_user_last_visit', ), array( $_SESSION['name'], $_SESSION['last_visit'], ) ); |
- Использование условий в шаблонах.
Синтаксис шаблонных условий:
| Цитата | --- template.htm {if %variable == %variable2} какой то текст {endif} <!-- Есть еще один вариант такого блока: --> {if %variable == 12} какой то текст {elseif} ошибка. {endif} |
Так же можно включать в условия циклы и константы. Для обработки и сравнения переменных в условиях используются значение и имена переменных из таблицы констант. То есть чтобы сравнить variable и variable2 необходимо добавить их в таблицу констант:
| Цитата | | $TemplateClass->Assign('variable', 12); |
- Циклы в шаблонах.
Синтаксис:
| Цитата | ---- template.htm <!-- вариант 1: индексно-цифровой массив --> <table> {loop loop_name} <tr><td>key: @index</td><td>value: @loop_name</td></tr> {endloop} </table> | Для объявления этого цикла необходимо добавить все необходимые атрибуты в таблицу циклов:
| Цитата | | $TemplateClass->AssignLoop('loop_name', array('a','b','c','d'), 'NUM'); | Первый аргумент функции принимает имя цикла. Второй - массив. Третий определяет тип индексов массива: существует два типа которые можно передать, это NUM и ASSOC. первый тип определен по умолчанию.
| Цитата | <!-- вариант 2: индексно-цифровой массив многомерный --> <table> {loop loop_name} <tr><td>key: @index</td><td>value: @loop_name[0], @loop_name[1] ... etc</td></tr> {endloop} </table> |
Собственно второй вариант ни чем не отличается от первого, как по синтаксису так и по занесению в таблиццу циклов, за исключением добавление индексов к квадратных скобках. Скрипт сам определяет многомерность массива.
| Цитата | <!-- вариант 3: индексно-ассоциативный массив --> <table> {loop loop_name} <tr><td>key: @index</td><td>value: @loop_name</td></tr> {endloop} </table> |
Вариант похож на первый, но разница в том что в качестве массива для обработки в таблицу циклов передается ассоциативный массив:
| Цитата | | $TemplateClass->AssignLoop('loop_name', array('a'=>1, 'b'=>2, 'c'=>3), 'ASSOC'); |
| Цитата | <!-- вариант 4: индексно-ассоциативный многомерный массив --> <table> {loop loop_name} <tr><td>key: @index</td><td>value: @loop_name[key1], @loop_name[key2] ... etc</td></tr> {endloop} </table> |
Думаю комментарии излишни.
- Компиляция шаблона.
Компиляция шаблона производится с помощью класса UD_TemplateCompiler:
| Цитата | | $TemplateCompiler = new UD_TemplateCompiler($TemplateClass); | После чего скомпилированный шаблон содержиться в перменной класса В_TemplateDocument Document:
| Цитата | | echo $TemplateClass->Document; |
Файл класса шаблона: | Цитата | ---- template.class.php <?php /* --------------------------------------------- */ // UD-TemplateDocument v1.2 // Класс для определения шаблонов. // © 2004 Beer Artur (izatop at mail.ru) // [#FileVersion 1.0] /* --------------------------------------------- */
class UD_TemplateDocument { var $Document = ''; // Текст шаблона. var $VarValues = array(); // Значения шаблонных переменных. var $VarKeys = array(); // Ключи шаблонных переменных. var $Variables = array(); // Дублируемые шаблонные перемнные для обработки условий. var $LoopTable = array(); // Таблица шаблонных циклов. var $LoopMatches = array(); // Таблица циклов шаблона. var $ConditionMatches = array(); // Таблица условий шаблона.
var $Headers = array(); // Заголовки шаблона. var $Options = array( // Опции компиляции шаблона. 'Debug' => 0, 'ParseVariable' => 1, 'ParseCondition' => 0, 'ParseLoop' => 0, ); // Конструктор. function UD_TemplateDocument($Document = '') { $this->Document = $Document; // Чтение заголовков и определение опций компиляции. $this->SetParseOptions($this->GetDocumentHeaders()); } function GetDocumentHeaders() { // Обработка заголовков шаблона. // Регулярное выражение для поиска заголовков в шаблоне. $Preg = "|<!--\s?ud:header\s?([a-zA-Z0-9_]*)\s?=\s?([a-zA-Z0-9_]*)\s?-->|s"; // Регулярное выражение для удаления служебных заголовков из шаблона. $PregR = "|\s?<!--\s?ud:header\s?([a-zA-Z0-9_]*)\s?=\s?([a-zA-Z0-9_]*)\s?-->\s?|s"; // Найти все заголовки и поместить в массив Headers. preg_match_all($Preg, $this->Document, $this->Headers); // Удалить все заголовки из шаблона. $this->Document = preg_replace($PregR, '', $this->Document); return true; } function SetParseOptions() { // Установить значения опций компиляции из шаблона заменив ими опции по умочанию. for($i = 0; $i < sizeof($this->Headers[1]); $i++) { $this->Options[$this->Headers[1][$i]] = $this->Headers[2][$i]; } } function Assign($Key, $Value) { // Инициализация переменных шаблона. if(is_array($Key)) { // Может принимать как отдельные значения, так и массивы. for($i = 0; $i < sizeof($Key); $i++) { $this->VarValues[] = $Value[$i]; $this->VarKeys[] = '%'.$Key[$i].'%'; $this->Variables[$Key[$i]] = $Value; } } else { $this->VarValues[] = $Value; $this->VarKeys[] = '%'.$Key.'%'; $this->Variables[$Key] = $Value; } return true; }
// Инициализация циклов шаблона. function AssignLoop($Name, $Loop, $Mode = 'NUM') { // Принимает три аргумента: // имя шаблона, массив который нужно обработать и вставить в цикл шаблона // и режим обработки массива - как индексно числовой (NUM) или как индексно ассоциативный (ASSOC). $this->LoopTable[] = array( 'Name' => $Name, 'Loop' => $Loop, 'Mode' => $Mode ); return true; } function FindLoop() { // Поиск шаблонных циклов. // регулярное выражение для поиска вхождений циклов в шаблоне. $Preg = "|{loop \s?([a-zA-Z0-9_]*)}(.*?){endloop}|s"; preg_match_all($Preg, $this->Document, $Matches); if(isset($Matches[0][0])) { // Преобразование полученных результатов для дальнейшей обработки в компиляторе. for($i = 0; $i < sizeof($Matches[0]); $i++) { $this->LoopMatches[$Matches[1][$i]][0] = $Matches[2][$i]; $this->LoopMatches[$Matches[1][$i]][1] = $Matches[1][$i]; $this->LoopMatches[$Matches[1][$i]][2] = $Matches[0][$i]; } return true; // Вернуть логическое "да" из функции при удачной обработке. } else { // Если вхождений не найдено, функция возращает логическое нет. return false; } } function FindCondition() { // Поиск шаблонных условий. // Регулярное выражение для поиска условий в шаблоне. $Preg = "|{if\s+?([a-zA-Z0-1_%]*)\s+?([=!<>]*)\s+?([a-zA-Z0-1_%]*)}(.*){endif}|s"; // При нахождении консрукций шаблонных условий они заносятся в массив ConditionMatches. preg_match_all($Preg, $this->Document, $this->ConditionMatches); return true; } }
/* --------------------------------------------- */ // UD-TemplateCompiler v1.1 // Класс для компиляции объектов шаблонов. // © 2004 Beer Artur (izatop at mail.ru) // [#FileVersion 1.0] /* --------------------------------------------- */
class UD_TemplateCompiler { function UD_TemplateCompiler(&$Template) { // Конструктор класса. $this->Compile($Template); } function Compile(&$Template) { // Компилятор шаблонов. if($Template->Options['ParseCondition']) { // Если опция компиляции условий включена: $Template->FindCondition(); // найти все вхождения конструкций шаблонных условий. for($i = 0; $i < sizeof($Template->ConditionMatches[0]); $i++) { // Если в условных блоках шаблона не встречаются блоки "или": if(!strpos($Template->ConditionMatches[4][$i], '{else}')) { // Разбор условий на составляющии и их обработка. $l = str_replace('%', '', trim($Template->ConditionMatches[1][$i])); $c = trim($Template->ConditionMatches[2][$i]); $r = str_replace('%', '',trim($Template->ConditionMatches[3][$i])); if(!is_numeric($l)) @$l = $Template->Variables[$l]; if(!is_numeric($r)) @$r = $Template->Variables[$r]; switch($c) { case '==': { if($l == $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } case '>': { if($l > $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } case '<': { if($l < $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } case '<=': { if($l <= $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } case '>=': { if($l >= $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } case '===': { if($l === $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } case '!=': { if($l != $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $Template->ConditionMatches[4][$i], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], '', $Template->Document); } } } } else { // Если в условных блоках шаблона встречаются блоки "или": // Разбор условий на составляющии и их обработка. $l = str_replace('%', '', trim($Template->ConditionMatches[1][$i])); $c = trim($Template->ConditionMatches[2][$i]); $r = str_replace('%', '',trim($Template->ConditionMatches[3][$i])); if(!is_numeric($l)) @$l = $Template->Variables[$l]; if(!is_numeric($r)) @$r = $Template->Variables[$r]; switch($c) { case '==': { if($l == $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } case '>': { if($l > $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } case '<': { if($l < $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } case '<=': { if($l <= $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } case '>=': { if($l >= $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } case '===': { if($l === $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } case '!=': { if($l != $r) { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } else { $Template->Document = str_replace($Template->ConditionMatches[0][$i], $ex[0], $Template->Document); } } } } } } // Компиляция шаблонных переменных: if($Template->Options['ParseVariable']) { // Если опции компиляции переменных включена. // Замена шаблонных перменных на значения. $Template->Document = str_replace($Template->VarKeys, $Template->VarValues, $Template->Document); } // Компиляция шаблонных циклов: if($Template->Options['ParseLoop']) { // Если опции компиляции циклов включены. if($Template->FindLoop()) { // Поиск шаблонных циклов. Если функция вернула логическое "да" - обработать. for($i = 0; $i < sizeof($Template->LoopTable); $i++) { // Если режим обработки массива цикла равен ASSO: switch($Template->LoopTable[$i]['Mode']) { case 'ASSOC': { // Обработать как индексно ассоциативный массив. $Key = key($Template->LoopTable[$i]['Loop']); if(is_array($Template->LoopTable[$i]['Loop'][$Key])) { foreach($Template->LoopTable[$i]['Loop'][$Key] as $key => $v) { $Fields[] = '@'.$Template->LoopTable[$i]['Name'].'['.$key.']'; } foreach($Template->LoopTable[$i]['Loop'] as $Index => $Value) { $Temp[] = @str_replace('@index', $Index, str_replace($Fields, $Value, $Template->LoopMatches[$Template->LoopTable[$i]['Name']][0])); } } else { foreach($Template->LoopTable[$i]['Loop'] as $Index => $Value) { $Temp[] = @str_replace('@index', $Index, str_replace('@'.$Template->LoopTable[$i]['Name'], $Value, $Template->LoopMatches[$Template->LoopTable[$i]['Name']][0])); } } $Template->Document = str_replace($Template->LoopMatches[$Template->LoopTable[$i]['Name']][2], implode('', $Temp), $Template->Document); break; } default: { // Если возвращается любое противоположенное значению ASSOC (например NUM), // обработать как индексно числовой. if(is_array($Template->LoopTable[$i]['Loop'][0])) { $Size = sizeof($Template->LoopTable[$i]['Loop'][0]); for($i = 0; $j < $Size; $j++) { $Fileds[] = '@'.$Template->LoopTable[$j]['Name'].'['.$j.']'; } for($j = 0; $j < sizeof($Template->LoopTable[$i]['Loop']); $j++) { $Temp[] = str_replace('@index', $j, str_replace($Fields, $Template->LoopTable[$i]['Loop'][$j], $Template->LoopMatches[$Template->LoopTable[$i]['Name']][0])); } } else { for($j = 0; $j < sizeof($Template->LoopTable[$i]['Loop']); $j++) { $Temp[] = str_replace('@index', $j, str_replace('@'.$Template->LoopTable[$i]['Name'], $Template->LoopTable[$i]['Loop'][$j], $Template->LoopMatches[$Template->LoopTable[$i]['Name']][0])); } } // Замена в шаблоне конструкций циклов на обработанные данные. $Template->Document = str_replace($Template->LoopMatches[$Template->LoopTable[$i]['Name']][2], implode('', $Temp), $Template->Document); break; } } unset($Temp); // Удаление временной таблицы с обработанными данными. } } } } } ?> |
|