Разработка TemplateEngine может кто подскажет

mymind

Новичок
Разработка TemplateEngine может кто подскажет

Прошу помощи. Сижу уж третий день. Не могу решить задачу. Подвис и всё тут. Может кто мыслю выскажет.

Проблема в обработке вложеных циклов в шаблоне. Значит система работает следующим образом. Первоначально шаблон инициализируется. В результате содержимое файла шаблона помещается в массив, под своим ключом

PHP:
$PAGE=new TEMPLATE;
$PAGE->ini("filetemplate.tpl","key");
Далее формируется массив из данных следующего вида
PHP:
$DATA["NAMEVAR"]="VALUEVAR";
//И собственно сама подстановка 
// выводим
$PAGE->insert("key","view",$DATA);
// или результат загоняем в переменную
$rezult=$PAGE->insert("key","return",$DATA);
Тут всё просто. Теперь шаблон. Тоже велосипеда не изобрел. Все переменные обозначаются {VAR}

Так вот возникла проблема с обработкой вложеных циклов. Отмечу, что обрабатывает также и условия, и вставки и формы. Но вот с циклами подвис. В шаблоне циклы выглядят следюущим образом (пример) :

PHP:
<ul type="square">
<!--BEGIN_"VC1"-->
<li>Основной цикл - проход {IVAR}
  <ul type="round">
  <!--BEGIN_"VC2"-->
    <li>Цикл вложеный уже {JVAR}</li>
  <!--END_"VC2"-->
  </ul>
</li>
<!--END_"VC1"-->
</ul>
Теперь результат. Что нужно получить :

Например :
Цикл VC1 имеет два прохода. А цикл VC2 при значении VC1=0 имеет два прохода, при VC1=1 имеет три прохода. Т.е в общем виде схема такая


При VC1=0
Имеет количетсво элементов в VC2=2

При VC1=1
Имеем количество элементов VC2=3


Ес-но, вложений неограниченно. И VC1 и VC2 - это всего лишь названия циклов. Т.е. может быть и CICLE и MYDATA тут неважно. Понятно, что после работы шаблонизатора, вся конструкция должна быть заменена на соовтетвующий результат. Т.е. пример должен выглядеть следлующим образом ( переменные IVAR и JVAR всего лишь счётчики) :

PHP:
- Основной цикл - проход 1
-- Цикл вложеный уже 1
-- Цикл вложеный уже 2

- Основной цикл - проход 2
-- Цикл вложеный уже 1
-- Цикл вложеный уже 2
-- Цикл вложеный уже 3

Значит данные, что передаю Я выглядят следующим образом :

PHP:
$DATA["VC1"]["ELEMENTS"]=2;

$DATA["VC1"][0]["IVAR"]=1;
$DATA["VC1"][0]["VC2"]["ELEMENTS"]=2;
$DATA["VC1"][0]["VC2"][0]=1;
$DATA["VC1"][0]["VC2"][1]=2;

$DATA["VC1"][1]["IVAR"]=2;
$DATA["VC1"][1]["VC2"]["ELEMENTS"]=3;
$DATA["VC1"][1]["VC2"][0]=1;
$DATA["VC1"][1]["VC2"][1]=2;
$DATA["VC1"][1]["VC2"][2]=3;
А вот дальше не знаю что делать. Пока сделал лишь такую штуку. Парсится шаблон и на основе результат парсинга рекурсивно формирую массив вида, которы написал выше. Ес-но значение выбираются просто. Сначала формирую строку вида к примеру
PHP:
$my_string="[\"VC1\"][".$counter."][\"VC2\"][\"ELEMENTS\"]";
eval("\$elements=\$DATA".$my_string.";");
echo "Кол-во проходов для цикла VC2 на данный момент= ".$elements;
И рекурсивно в итоге можно построить дерево массива. Проблем нет. Но вот, как дальше поступить. Даже не представляю. :( Может просто усталость говорит. Проблема в том, чтобы на основе данных сформировать итоговый HTML, который заменит в результате сабой шаблонные команды.

Пока думаю так. В массив помещаются тела всех циклов. Когда рекурсия добежала до самого глубоко цикла, начинаем обрабатывать это тело на наличие переменных и их значение. А вот дальше как ? Просто заменить тело цикла на результат не вкатывает. Короче идеи пока подвисли. Может у кого есть какая мысля. Чиркните. Любая искорка поможет разгореться пламяни.
 

WP

^_^
А можно поинтересоваться почему управляющие конструкции в шаблоне записываются как комментарии в HTML?
 

mymind

Новичок
А можно поинтересоваться почему управляющие конструкции в шаблоне записываются как комментарии в HTML?
Вообще мне так показалось наиболее удобным. В конечном итоге определённого стандарта на это нет, а при вёрстке оказалось, что так гораздо проще для тех, кто верстает.
 

atv

Новичок
Например :
Цикл VC1 имеет два прохода. А цикл VC2 при значении VC1=0 имеет два прохода, при VC1=1 имеет три прохода.
Т.е. под проходами ты имееш ввиду количество итераций. Тогда не понятно
Парсится шаблон и на основе результат парсинга рекурсивно формирую массив вида, которы написал выше.
Количество итераций (проходов) должно определяться входными данными, а шаблон только задаёт как отображать один элемент даных.

Не совсем понятно описание алгоритма:
В результате содержимое файла шаблона помещается в массив, под своим ключом
В каком виде помещается, распарсеном? Что собой представляет этот массив?

Приведи код функции insert().
 

mymind

Новичок
Т.е. под проходами ты имееш ввиду количество итераций.
Да, именно так. Просто ночью уже писал, слово выпало из головы. В итоге ничего умней не нашел, чем прописать проходы.


Количество итераций (проходов) должно определяться входными данными, а шаблон только задаёт как отображать один элемент даных.
Всё верно. Количество итераций определяется входными данными.


В каком виде помещается, распарсеном? Что собой представляет этот массив?
Когда вызывается $PAGE->ini("filetemplate.tpl","key"); то содержимое файла считывается и помещается в ассоциативный массив. $CONTENT["key"]=содержимой файла filetemplate.tpl

Когда же мы подаём данные, то шаблон берётся уже не из файла, а из массива. Но в массиве хранится содержимое шаблона не в распарсеном виде. Как есть. Со всем управляющими конструкциями и прочее. И парсится начинает, только после того, как нам это нужно.

Функция insert основная, она сначала вызываетс parser для управляющих структур, а потом оставшиеся переменные заменяет.

PHP:
function insert($key,$rezult,$data){
// вытаскиваем шаблон по ключу
$content=$this->template[$key]; 
// запускаем парсер на управляющие конструкции
$content=$this->parser($content,$data);
// теперь остаточные данные
if ($data){
	foreach ($data as $k => $v){
	$eregi_string="{".$k."}";
	$content=str_replace($eregi_string,$v,$content);
	}
}

//остальные пременные, если таковые есть убираем в нуль
$content=preg_replace("/{([a-z0-9_]+)}/ims","",$content);
//возврат результата
if ($rezult=='view'){
	echo $content;
	}
	else {
	return $content;
	}
}
Теперьт, функция parser состоит из множетсва функций, но для цикла я приведу

PHP:
function cycle_parse($content,$data,$level_varible){
preg_match_all("/<!--BEGIN_\"([a-z0-9_]+)\"-->(.*?)<!--END_\"\\1\"-->/ims",$content,$ok);
//Количество циклов в системе
$now_me_taked=count($ok[1]);
//Перебираем все найденные циклы
for ($i=0;$i<$now_me_taked;$i++){
//Название переменной для цикла
$name_var_cycle=$ok[1][$i];
//Тело цикла
$body=$this->for_eregi($ok[2][$i]);
//echo $name_var_cycle."<br>";
//Ищем а есть ли такая переменная в системе
$level_varible.="[\"".$name_var_cycle."\"]";
eval("\$counter_value=\$data".$level_varible."[\"ELEMENTS\"];");
	for ($j=0;$j<$counter_value;$j++){
	//$this->$_VC[$level_varible]=$body;
	$level_varible_info=$level_varible."[".(($j) ? $j : 0)."]";
	//echo $level_varible_info."<br>";
	$body=$this->cycle_parse($body,$data,$level_varible_info);
	$tt="\$info_data=\$data".$level_varible_info.";";
		eval($tt);
		//echo $tt."<br>";
		//echo count($info_data)."<br>";
		//echo $info_data["UJ"]."<br>";
		foreach ($info_data as $k => $v){
		echo $k."=".$v."<br>";
		}
	}
}

return $content;
}
Первое обращение выглядет так :
PHP:
$content=$this->cycle_parse($content,$data,'');
Функция for_eregi вспомогательная. На неё не надо обращать внимание.

Т.е. если посмотреть результат, то эта функция связывает шаблон и массив данных. И собственно начинает обрабатывать оставшиеся переменные только достигнув самой большой глубины.
 

atv

Новичок
Я бы не получал количество всех циклов в системе $now_me_taked, а нашёл бы только блок (в смысле цикл) верхних уровней и обработал бы его. Эту обработку оформить в виде функции и вызывать рекурсивно для вложенных блоков.

Если по порядку:
Получаем в insert()-е входные данные. Если данные это массив, то логично предположить что для них должен быть блок.

Отсюда начинается рекурсия.

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

Размещаем в нём данные и так для каждого элемента данных.

Если отдельный елемент данных - это массив, значит ищем для них блок, но уже в контексте текущего блока.
 

mymind

Новичок
О ! Спасибо, понял. Попробую реализовать. Мысль более чем ясна. Подсказка уже навела на решение.
 
Сверху