За последние 24 часа нас посетили 22896 программистов и 1263 робота. Сейчас ищут 733 программиста ...

Шаблонизатор. Подходы реализации include

Тема в разделе "Прочие вопросы по PHP", создана пользователем AterCattus, 14 окт 2008.

  1. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Доброго времени суток! Вот решил немного пообщаться по поводу идей и реальных подходов к построению шаблонизатора. Написано по этой теме много, реализаций имхо еще больше, но я давно уже проектирую и потихоньку разрабатываю свою CMF. В основе требования реальных проектов, а не желание создать "мега-крутую супер-пупер CMF" ;-) Цель свою она выполняет. Но это так, введение.
    И есть уже реально работающий модуль шаблонизатора, направленный на упрощение работы дизайнера и компоновщика, а не программиста ( "лапша" в шаблоне приведет к ошибке парсинга ). Все хорошо, но один момент меня особенно интересует: реализация include. Хотелось бы выслушать ваши предложения и идеи по этому поводу: как лучше и в каких случаях? Сейчас происходит полный парсинг всех include и их включение в итоговый файл. Это имхо ужасно, но ничего лучше я не придумал при реализации include внутри ветвлений.

    Уже перебрал несколько систем со своими шаблонизаторами, посмотрел как в них, но хотел бы услышать мнения форумчан.
     
  2. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    лучше вообще без инклудов,
    а вообще, можно ещё сначало заинклудить, а потом парсить =))
     
  3. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    ну как без них?
    {include header.tmpl}
    do smth...
    {include footer.tmpl}

    а в header.tmpl например содержится {if xxxx } {include yyyy } {else} { include zzzzz }

    Очень полезно временами.

    >>а вообще, можно ещё сначало заинклудить, а потом парсить =))
    А если в инклудах нужны разные переменные или они даже одноименные, но в разных шаблонах по разному используются? Если все скинуть в один файл, то могут возникать конфликты.
    У меня была безумная мысль проверять условия входа в инклуд, но отбросил почти сразу: высокая сложность и низкая скорость. Сейчас класс шаблонизатора 814 строк (26КБ) и парсинг страницы пр первом проходе занимает 1-50 мсек. Не хочется сильно усложнять. Вот и спрашиваю предложений.
     
  4. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Здравый смысл подсказывает - не делайте парсеры шаблонов на PHP - PHP сам парсер!
     
  5. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Я ж написал, что делается для компоновщиков.
    Удобнее же написать например так:
    PHP:
    1. {foreach elem in vector}
    2.    <td>{elem}</td>
    3. {/foreach}
    4.  
    нежели так:
    PHP:
    1. <?php foreach ( $vector as $elem ) : ?>
    2. <td><?php echo $elem ?></td>
    3. <?php endforeach ?>
    Да и часто разделение на модель и вид делает код логичнее и последовательнее.
     
  6. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    тоесть тут есть разделение
    PHP:
    1. {foreach elem in vector}
    2.    <td>{elem}</td>
    3. {/foreach}
    4.  
    а тут нет
    PHP:
    1. <?php foreach ( $vector as $elem ) : ?>
    2. <td><?php echo $elem ?></td>
    3. <?php endforeach ?>
    ?
     
  7. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    парсить шаблоны нижнего уровня в пхп, потом результат вставлять в другой шаблон в виде переменной
    вот и всё...
     
  8. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    >>Sergey89

    Это не пример разделения. Я даже не писал такого! Фраза "часто разделение на модель и вид..." идет после кода и, более того, начинается с "Да и". Вроде по-русски написал.

    Давайте не будем спорить о необходимости введения шаблонизатора, а то получается нечто подобное:
    - Как в WinVista сделать ...
    - Поставь WinXP!
    :)
     
  9. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    пример на смарти
    PHP:
    1. <?
    2. $result=array();
    3.  
    4. if($d) {
    5.    $tpl->assign('info','ggg');
    6.    $result['content']=$tpl->fetch('text.tpl');
    7.    $tpl->assign('error','No Error');
    8.    $result['error']=$tpl->fetch('error.tpl');
    9. }else {
    10.    $tpl->assign('error','Super Puper Error');
    11.    $result['error']=$tpl->fetch('error.tpl');
    12. }
    13.  
    14. $tpl->assign($result);
    15. $tpl->display('main.tpl');
    16. ?>
     
  10. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Давайте. Вот только назови мне отличия двух представленных вариантов.
     
  11. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Mr.M.I.T.>
    Гм, что значит "вставить в виде переменной"?

    Вот например такой надуманный пример:
    PHP:
    1. {if auth}
    2.     Hello, {include name.tmpl}
    3. {else}
    4.     {include auth.tmpl}
    5. {/fi}
    6.  
    7.  
    8. name.tmpl:
    9. {name.first} {name.second}
    10.  
    11. auth.tmpl:
    12. <form>
    13.     <input value="{input.value}">
    если пользователь авторизован - переменная input.value не факт, что вообще определена в скрипте, ну и наоборот для name.*.
    Как поступить в таком случае?
     
  12. QQQ

    QQQ Активный пользователь

    С нами с:
    21 ноя 2007
    Сообщения:
    538
    Симпатии:
    0
    а зачем так изгиляться?
     
  13. Sergey89

    Sergey89 Активный пользователь

    С нами с:
    4 янв 2007
    Сообщения:
    4.796
    Симпатии:
    0
    Переменная var из шаблона aaa.tpl лежит в $vars['aaa']['var'], а для шаблона bbb.tpl в $vars['bbb']['var']. Просто учитывать это при парсинге.
     
  14. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    AterCattus
    Всегда есть прослойка между шаблоном и приложением, которая обрабатывает случаи отсуствия переменной. В моём случае возвращается пустота.

    Во вторых у вас в корне неправильный пример. Подключать тот или иной шаблон нужно на уровне логики приложения, а не шаблона. т.е. у вас приложение должно вызвать либо шаблон name.tmpl либо auth.tmpl. У вас бизнес логика в шаблоне оказалась. Я за такое бъю по рукам и заставляю переделать.

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

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Sergey89
    Иногда одна переменная нужна в нескольких шаблонах, когда модуль выводит несколько блоков. Для каждого блока устанавливать в шаблонизатор отдельно переменную глупо, а если она ещё и объёмная?
    А ещё есть глобальные переменные для всего приложения, тоже между прочим требуемые в каждом шаблоне, к примеру URL нашего сайта :)
     
  16. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    >"пример на смарти"
    вижу. предлагаешь перенести логику выбора отображаемых страниц на php?

    >Psih
    Пример надуман, я написал же.
    В данном случае хотел показать вариант отображения блока авторизации в шапке сайта: или что-то типа "Привет, Вася" или вывод формы авторизации в этом же блоке. Тут никакого редиректа не нужно - только вывод разных блоков со своими полями.

    У меня сейчас как:
    PHP:
    1. $view = &load_class( 'templater' );
    2. $view=>set( 'auth', ( $CUR_USER !== FALSE ) );
    3. ...
    4. $view->set( 'smth', $smth );
    5. ...
    6. $view->fdisplay( ADMIN_TEMPLATES . '/'.$id.'.html' );
    HTML:
    1.     <head>
    2.         {charset 'windows-1251'}
    3.         {title 'Примерчик'}
    4.         {include_css 'main.css'}
    5.         {include_js 'main.js'}
    6.     </head>
    7.     <body>
    8.         <div class="header">
    9.             <span class="title">{page.title}</span>
    10.         </div>
    11. {include 'menu.html'}
    12. <div class="main_div">......
     
  17. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    {include_css 'main.css'}
    {include_js 'main.js'}
    Накой оно надо - хз. Прописывается статично раз и навсегда. Тоже самое и с кодировкой.
     
  18. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    Да это макросы. Ну не удалил. Я хотел показать include - все же к нему идет.
    Хотя нет, могут быть разные стили в зависимости от ситуации ( не main.js, а что-то другое, либо еще файл при некотором условии подгрузить ).

    Вот пример условия подключения: вывод новостей только на главной. При этом дизайн отличается немного ( к примеру некий визуальный разделитель ). Это реально было и использовалось:
    PHP:
    1. {if page_url eq 'mail'}{include 'news'}{fi}
    Тут что, тоже выносить логику в модель?
    PHP:
    1. if ( $page_url == 'mail' ) $news_bock = parse_file('news'); else $news_block = ''; $view->set( 'nb', $news_block );
    PHP:
    1. {nb}
    Это разве лучше?
     
  19. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    иногда спорно, если загнать JS и CSS в кэш браузера, чтоб постоянно с сайта не тянулся, то при смене файлов удобно в имени файлов ещё версию указывать. Если работу с жабаскриптом, цсс перенести в админку, то почему бы и нет? Единственное, что это касается только проектов, постоянно меняющих и наращивающих JS функционал.
     
  20. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    >>Luge
    Плюс, если страница формируется из блоков, то нужно подгружать только то, что нужно на этой странице, а не все, что может понадобиться на сайте. Работал в том году немного с одной фирмой, так там система была на Perl+jS и Js-скрипты подключались на сервере множественными проверками необходимости, т.к. было их не одна сотня метров.
     
  21. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    решается отложенной загрузкой
     
  22. AterCattus

    AterCattus Активный пользователь

    С нами с:
    6 фев 2008
    Сообщения:
    80
    Симпатии:
    0
    Адрес:
    Санкт-Петербург
    >решается отложенной загрузкой
    если подключать в шапке, то к моменту рендера самого блока стили и т.п. уже могут загрузиться. да и вставлять ссылки на ресурсы в теле страницы как-то мне не хочется.

    А все-таки, что насчет include? Если тут все хотят лишь показать как плохо использовать шаблонизатор, то не вижу смысла дальше дискутировать. Я попросил совета в вопросе, а мне в ответ - ну его.
     
  23. Psih

    Psih Активный пользователь
    Команда форума Модератор

    С нами с:
    28 дек 2006
    Сообщения:
    2.678
    Симпатии:
    6
    Адрес:
    Рига, Латвия
    Шаблонизатор это хорошо, просто я не принимаю подхода с написанием парсера шаблонов на PHP.
    Все шаблонизаторы используют include.
     
  24. Luge

    Luge Старожил

    С нами с:
    2 фев 2007
    Сообщения:
    4.680
    Симпатии:
    1
    Адрес:
    Минск
    в плане реализации ещё одного языка программирования, написанного на пхп, да ну его.
     
  25. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
    Угу, всегда так делаю, в шаблоне будет посто {$head} {$footer} и тд,
    ещё в смарти можно объект вставить, тогда вообще классно, можно прямо из шаблона управлять блоками пхп
    вот например у меня авторизация выводится
    {$plugin->get_auth()} а можно и не выводить,тогда и метод get_auth не будет отрабатываться пхп