Доброго времени суток! Вот решил немного пообщаться по поводу идей и реальных подходов к построению шаблонизатора. Написано по этой теме много, реализаций имхо еще больше, но я давно уже проектирую и потихоньку разрабатываю свою CMF. В основе требования реальных проектов, а не желание создать "мега-крутую супер-пупер CMF" ;-) Цель свою она выполняет. Но это так, введение. И есть уже реально работающий модуль шаблонизатора, направленный на упрощение работы дизайнера и компоновщика, а не программиста ( "лапша" в шаблоне приведет к ошибке парсинга ). Все хорошо, но один момент меня особенно интересует: реализация include. Хотелось бы выслушать ваши предложения и идеи по этому поводу: как лучше и в каких случаях? Сейчас происходит полный парсинг всех include и их включение в итоговый файл. Это имхо ужасно, но ничего лучше я не придумал при реализации include внутри ветвлений. Уже перебрал несколько систем со своими шаблонизаторами, посмотрел как в них, но хотел бы услышать мнения форумчан.
ну как без них? {include header.tmpl} do smth... {include footer.tmpl} а в header.tmpl например содержится {if xxxx } {include yyyy } {else} { include zzzzz } Очень полезно временами. >>а вообще, можно ещё сначало заинклудить, а потом парсить =)) А если в инклудах нужны разные переменные или они даже одноименные, но в разных шаблонах по разному используются? Если все скинуть в один файл, то могут возникать конфликты. У меня была безумная мысль проверять условия входа в инклуд, но отбросил почти сразу: высокая сложность и низкая скорость. Сейчас класс шаблонизатора 814 строк (26КБ) и парсинг страницы пр первом проходе занимает 1-50 мсек. Не хочется сильно усложнять. Вот и спрашиваю предложений.
Я ж написал, что делается для компоновщиков. Удобнее же написать например так: PHP: {foreach elem in vector} <td>{elem}</td> {/foreach} нежели так: PHP: <?php foreach ( $vector as $elem ) : ?> <td><?php echo $elem ?></td> <?php endforeach ?> Да и часто разделение на модель и вид делает код логичнее и последовательнее.
тоесть тут есть разделение PHP: {foreach elem in vector} <td>{elem}</td> {/foreach} а тут нет PHP: <?php foreach ( $vector as $elem ) : ?> <td><?php echo $elem ?></td> <?php endforeach ?> ?
парсить шаблоны нижнего уровня в пхп, потом результат вставлять в другой шаблон в виде переменной вот и всё...
>>Sergey89 Это не пример разделения. Я даже не писал такого! Фраза "часто разделение на модель и вид..." идет после кода и, более того, начинается с "Да и". Вроде по-русски написал. Давайте не будем спорить о необходимости введения шаблонизатора, а то получается нечто подобное: - Как в WinVista сделать ... - Поставь WinXP!
пример на смарти PHP: <? $result=array(); if($d) { $tpl->assign('info','ggg'); $result['content']=$tpl->fetch('text.tpl'); $tpl->assign('error','No Error'); $result['error']=$tpl->fetch('error.tpl'); }else { $tpl->assign('error','Super Puper Error'); $result['error']=$tpl->fetch('error.tpl'); } $tpl->assign($result); $tpl->display('main.tpl'); ?>
Mr.M.I.T.> Гм, что значит "вставить в виде переменной"? Вот например такой надуманный пример: PHP: {if auth} Hello, {include name.tmpl} {else} {include auth.tmpl} {/fi} name.tmpl: {name.first} {name.second} auth.tmpl: <form> <input value="{input.value}"> если пользователь авторизован - переменная input.value не факт, что вообще определена в скрипте, ну и наоборот для name.*. Как поступить в таком случае?
Переменная var из шаблона aaa.tpl лежит в $vars['aaa']['var'], а для шаблона bbb.tpl в $vars['bbb']['var']. Просто учитывать это при парсинге.
AterCattus Всегда есть прослойка между шаблоном и приложением, которая обрабатывает случаи отсуствия переменной. В моём случае возвращается пустота. Во вторых у вас в корне неправильный пример. Подключать тот или иной шаблон нужно на уровне логики приложения, а не шаблона. т.е. у вас приложение должно вызвать либо шаблон name.tmpl либо auth.tmpl. У вас бизнес логика в шаблоне оказалась. Я за такое бъю по рукам и заставляю переделать. З.Ы. По хорошему если не авторизован и требуется авторизация - надо делать перенаправление на форму авторизации, а не подменять шаблон. Вот так народ и пишет, а потом удивляется почему так тяжело вносить изменения, появляются баги и начинает непонятно почему глючить. Я уже не говорю о том, что когда система усложняется, то появляются большие блоки условий в вариантами действий.
Sergey89 Иногда одна переменная нужна в нескольких шаблонах, когда модуль выводит несколько блоков. Для каждого блока устанавливать в шаблонизатор отдельно переменную глупо, а если она ещё и объёмная? А ещё есть глобальные переменные для всего приложения, тоже между прочим требуемые в каждом шаблоне, к примеру URL нашего сайта
>"пример на смарти" вижу. предлагаешь перенести логику выбора отображаемых страниц на php? >Psih Пример надуман, я написал же. В данном случае хотел показать вариант отображения блока авторизации в шапке сайта: или что-то типа "Привет, Вася" или вывод формы авторизации в этом же блоке. Тут никакого редиректа не нужно - только вывод разных блоков со своими полями. У меня сейчас как: PHP: $view = &load_class( 'templater' ); $view=>set( 'auth', ( $CUR_USER !== FALSE ) ); ... $view->set( 'smth', $smth ); ... $view->fdisplay( ADMIN_TEMPLATES . '/'.$id.'.html' ); HTML: <html> <head> {charset 'windows-1251'} {title 'Примерчик'} {include_css 'main.css'} {include_js 'main.js'} </head> <body> <div class="header"> <span class="title">{page.title}</span> </div> {include 'menu.html'} <div class="main_div">......
{include_css 'main.css'} {include_js 'main.js'} Накой оно надо - хз. Прописывается статично раз и навсегда. Тоже самое и с кодировкой.
Да это макросы. Ну не удалил. Я хотел показать include - все же к нему идет. Хотя нет, могут быть разные стили в зависимости от ситуации ( не main.js, а что-то другое, либо еще файл при некотором условии подгрузить ). Вот пример условия подключения: вывод новостей только на главной. При этом дизайн отличается немного ( к примеру некий визуальный разделитель ). Это реально было и использовалось: PHP: {if page_url eq 'mail'}{include 'news'}{fi} Тут что, тоже выносить логику в модель? PHP: if ( $page_url == 'mail' ) $news_bock = parse_file('news'); else $news_block = ''; $view->set( 'nb', $news_block ); PHP: {nb} Это разве лучше?
иногда спорно, если загнать JS и CSS в кэш браузера, чтоб постоянно с сайта не тянулся, то при смене файлов удобно в имени файлов ещё версию указывать. Если работу с жабаскриптом, цсс перенести в админку, то почему бы и нет? Единственное, что это касается только проектов, постоянно меняющих и наращивающих JS функционал.
>>Luge Плюс, если страница формируется из блоков, то нужно подгружать только то, что нужно на этой странице, а не все, что может понадобиться на сайте. Работал в том году немного с одной фирмой, так там система была на Perl+jS и Js-скрипты подключались на сервере множественными проверками необходимости, т.к. было их не одна сотня метров.
>решается отложенной загрузкой если подключать в шапке, то к моменту рендера самого блока стили и т.п. уже могут загрузиться. да и вставлять ссылки на ресурсы в теле страницы как-то мне не хочется. А все-таки, что насчет include? Если тут все хотят лишь показать как плохо использовать шаблонизатор, то не вижу смысла дальше дискутировать. Я попросил совета в вопросе, а мне в ответ - ну его.
Шаблонизатор это хорошо, просто я не принимаю подхода с написанием парсера шаблонов на PHP. Все шаблонизаторы используют include.
Угу, всегда так делаю, в шаблоне будет посто {$head} {$footer} и тд, ещё в смарти можно объект вставить, тогда вообще классно, можно прямо из шаблона управлять блоками пхп вот например у меня авторизация выводится {$plugin->get_auth()} а можно и не выводить,тогда и метод get_auth не будет отрабатываться пхп