Есть вот такой класс, отвечающий за все, что связано с шаблонами. Код тут кривой, но для более хорошего моих знаний пока не хватает. Код (PHP): <?php class Template { //Содержимое файла private $html; //Директория шаблонов private $dir; //Директория кэша private $dir_cache; //Имя файла private $name; //Значение private $value; //Что заменять private $start_tag; public function __construct() { require $_SERVER["DOCUMENT_ROOT"].'/test/system/class/Config.class.php'; $this->dir=$dir."system/html/Template/"; $this->dir_cache=$dir."system/html/Template/cache/cache.php"; $this->start_tag=array( "/\{% ?for (\w*)=(\w*); ?\w*([<=>]*)(\w*); ?\w*([-\+]*) ?%\}([\s\S]*){% ?\/for ?%\}/i", "/\{% ?if ([\w<=> ]*) ?%\}([\s\S]*)\{% ?else ?%\}([\s\S]*)\{% ?\/if ?%\}/i", "/\{% ?if ([\w<=> ]*) ?%\}([\s\S]*)\{% ?\/if ?%\}/i", "/\{% ?foreach ([\w'=>,\(\)]*) as (\w*) ?%\}([\s\S]*)\{%\/foreach%\}/", "/\{% ?foreach ([\w'=>,\(\)]*) as (\w*) ?=> ?(\w*) ?%\}([\s\S]*)\{%\/foreach%\}/", ); } //Выводим содержимое public function start($values,$name) { $this->name=$name; $this->open(); $this->set_val($values); require $this->dir_cache; } //открываем шаблон для считывания private function open() { if($this->html_[$this->name]==NULL) { $this->html_[$this->name]=join('',file($this->dir.$this->name.'.tpl')); $this->html[$this->name]=$this->html_[$this->name]; } else { $this->html[$this->name]=$this->html_[$this->name]; } } //Присваиваем значения private function set_val($values) { foreach($values as $ind=>$val) { $this->value[$ind]=$val; } $this->replace(); } //Заменяем значения private function replace() { foreach($this->value as $ind=>$val) { $key='{'.$ind.'}'; if(is_array($val)) { $this->html[$this->name]=str_replace($key,$this->save_mass($val),$this->html[$this->name]); } else { $this->html[$this->name]=str_replace($key,$val,$this->html[$this->name]); } } $this->for_(); $this->if_(); $this->foreach_(); $cache=fopen($this->dir_cache,'w+'); fwrite($cache,$this->html[$this->name]); fclose($cache); } //------Обработка-------------- private function for_() { preg_match_all($this->start_tag[0],$this->html[$this->name],$res); foreach($res[0] as $ind=>$str) { $res="<?php for(\${$res[1][$ind]}={$res[2][$ind]};\${$res[1][$ind]}{$res[3][$ind]}{$res[4][$ind]};\${$res[1][$ind]}{$res[5][$ind]}) { ?>".str_replace("{{$res[1][$ind]}}","<?php echo $".$res[1][$ind]."; ?>",$res[6][$ind])."<?php } ?>"; $this->html[$this->name]=str_replace($str,$res,$this->html[$this->name]); } } private function if_() { preg_match_all($this->start_tag[1],$this->html[$this->name],$res); preg_match_all($this->start_tag[2],$this->html[$this->name],$res_); foreach($res[0] as $ind=>$str) { $result="<?php if({$res[1][$ind]}) { ?>{$res[2][$ind]}<?php } else { ?>{$res[3][$ind]}<?php } ?>"; $this->html[$this->name]=str_replace($str,$result,$this->html[$this->name]); } foreach($res_[0] as $ind=>$str) { $result="<?php if({$res_[1][$ind]}) { ?>{$res_[2][$ind]}<?php } ?>"; $this->html[$this->name]=str_replace($str,$result,$this->html[$this->name]); } } private function foreach_() { preg_match_all($this->start_tag[3],$this->html[$this->name],$res); preg_match_all($this->start_tag[4],$this->html[$this->name],$res_); foreach($res[0] as $ind=>$str) { $result="<?php foreach({$res[1][$ind]} as \${$res[2][$ind]}) { ?>".str_replace("{{$res[2][$ind]}}","<?php echo \${$res[2][$ind]}; ?>",$res[3][$ind])."<?php } ?>"; $this->html[$this->name]=str_replace($str,$result,$this->html[$this->name]); } foreach($res_[0] as $ind=>$str) { $result="<?php foreach({$res_[1][$ind]} as \${$res_[2][$ind]}=>\${$res_[3][$ind]}) { ?>".str_replace("{{$res_[2][$ind]}}","<?php echo \${$res_[2][$ind]}; ?>",str_replace("{{$res_[3][$ind]}}","<?php echo \${$res_[3][$ind]}; ?>",$res_[4][$ind]))."<?php } ?>"; $this->html[$this->name]=str_replace($str,$result,$this->html[$this->name]); } } //Разбиение массива на строку private function save_mass($mass) { $str="array("; foreach($mass as $ind=>$val) { $str.="'{$ind}'=>'{$val}',"; } $str.=")"; return $str; } } По порядку: вызываем мы вот такой строчкой. Код (PHP): $th=new Template(); $test=array(1,5,7); $th->start(array( 'text'=>'Главная', 'num'=>5, 'test'=>$test ),'index'); Пример шаблона: Код (PHP): <div>{text}</div> <br> {%for i={num};i<8;i++%} {i}<br> {%/for%} {%if {num}==5%} 4 {%else%} 5 {%/if%} <br><br> {%foreach {test} as ind=>val%} {ind}-{val}<br> {%/foreach%} Далее наш класс открывает шаблон с заданным именем. Если он уже открыт, берет значение из уже существующей переменной. Все это дело он присваивает переменной $html. Далее все наши переданные значения он кидает в массив и начинает их замену. Как он это делает: Первым делом заменяем все имена переменных из шаблона на значения из массива(ищем по ключу), если же имя переменной - массив, он превращает ее в строку функцией save_mass для корректности работа скомпилированного позже php кода. Далее по очереди заменяем регулярками for, if и foreach. После того, как текст шаблона полностью редактирован и готов к выводу, весь php код нужно скомпилировать. Тут и проблема. Как я это сделал: Просто создал файл cache.php, в котрый я помещаю этот самый код, а потом просто подключаю этот самый файл к странице, тем самым выводя результат. Но что будет, если, скажем, одновременно человек 50 будут загружать страницу? Серверу просто не хватит времени на запись и вывод из файла кода у каждого пользователя, и у одного пользователя будет выводиться то, что должно вывестись у другого. Как правильно можно откомпилировать весь php код в шаблоне? На ум приходит только eval, но тогда весь остальной код придется помещать в echo, чтобы не было такого: eval("}") PHP, JavaScript, SQL и другой код пишите внутри тегов Код ( (Unknown Language)): [b]php][/b]Тут код[b][/[/b][b]code][/b][/color]
Как правило заводится директория cache и в неё складываются скомпилированные файлы со случайными именами
Смысл еще в том, что эти файлы можно использовать повторно, если страница не менялась, без перекомпиляции
Большинство шаблонов выводят динамическую информацию из базы, а извлекается она не в самом шаблоне, а при передаче в него значений, так что все равно придется менять значения
В таком случае, страничка разбивается на множество мелких кэширующихся шаблонов. Часть из них может жить без изменений довольно долго. Просто подели количество изменений на страницах в день на количество просмотров страниц и поймешь, насколько это круто. Добавлено спустя 1 минуту 32 секунды: Тут вот есть достаточно содержательный топик viewtopic.php?f=27&t=11926
Идею понял, спасибо Добавлено спустя 27 минут: Остановился пока что на таком Код (Text): class Template { //Директория шаблонов private $dir; //Имя файла private $name; //Значение private $value; public function __construct() { require $_SERVER["DOCUMENT_ROOT"].'/test/system/class/Config.class.php'; $this->dir=$dir."system/html/Template/"; } //Выводим содержимое public function start($values,$name) { $this->name=$name; $this->set_val($values); $this->open(); } //открываем шаблон для считывания private function open() { foreach($this->value as $ind=>$val) { $$ind=$val; } require $this->dir.$this->name.'.php'; } //Присваиваем значения private function set_val($values) { foreach($values as $ind=>$val) { $this->value[$ind]=$val; } } } Шаблоны будут иметь вид Код (Text): <div><? echo $text ?></div> <br> <div><? echo $num ?></div> <br> <? foreach($test as $t) { echo $t; } ?> Вызов так же. И времени гораздо меньше на обработку
rodent90, нет ничего дурного в том чтобы использовать родные PHP файлы в качестве шаблонов. надеюсь цель автора цель в изолировании представления от всего прочего и она выполняется. если у кого-то цель создать новый "более лучший" язык разметки — вот тут стоило бы насторожиться ))) примеры шаблонизаторов с нативными пхп-шными шаблонами: http://platesphp.com/ , http://symfony.com/doc/current/components/templating/index.html да и ларавелевский blade почти ничего не изобретает, все выражения копирутся дословно, функции никак не ограничиваются. в своем шаблонизаторе я поддержал такой подход ))) danies, вместо <? echo $text ?> пиши <?= $text ?> короткие теги считаются плохим стилем, в отличие от ехо-тега. кроме того, мне кажется неудобным множество вызовов $o->set_val(), вместо того чтобы один раз закинуть всё необходимое при открытии шаблона. лично для меня вот так в самый раз: Код (PHP): $view->render('mytemplate', compact('alfa', 'beta', 'gama'));
artoodetoo. Мне не нравится такой подход. Не один из перечисленных мне не понравился тем, что у них вперемешку все. Вообще не по теме. Код (PHP): {{ isset($name) ? $name : 'Default' }} - убожество проще тогда вообще не ставить такой шаблонизатор.
ты о чем вообще? ))) если о блейде, то там написано: "вместо вот этого убожества вы можете написать {{$x or 'Default'}} " но ты видишь только то, что хочешь видеть, кажется. ))) лучше расскажи какой подход тебе НЕ кажется убожеством.
Я перепробовал массу шаблонизаторов и мне просто не понравилось это все, решил остаться на просто php =) Код (PHP): <?=func()?> <?=$var?> Я все обработки делаю до вывода, а в вывод отправляю либо функцию либо переменную.