Понакрутили, понавертели! Я вот юзаю простенький шаблонизатор и доволен. Всего 2 метода: PHP: <?php $TPL->block('pm/inbox_body.tpl', 'pm_inbox', $pm_inbox); $TPL->parse('link.tpl', 1, array('href' => HTTP.DOMAIN.PATH.SCRIPT_FILENAME.'?m=users&a=profile&id='.$row['sender'].SID, 'value' => htmlspecialchars($row['user_login']))) Всё =) Все циклы и прочая хрень делается на чистом пэхапэ. // приведённые методы - это лишь вершина айсберга, многое делается автоматом внутри класса, да и у этих методов несколько режимов работы =) // Весь шаблонизатор - 118 строк кода, масюсенький такой. // и не наезжать на меня!!! не хочу тут с вами спорить =)
Показываю цикл: PHP: <?php while($row = $DB->fetch_assoc($result)) { $pm_inbox[] = array('create_date' => ***_date('j.n.Y G:i:s', $row['create_date']), 'sender' => (!$row['user_delete'])? $TPL->parse('link.tpl', 1, array('href' => HTTP.DOMAIN.PATH.SCRIPT_FILENAME.'?m=users&a=profile&id='.$row['sender'].SID, 'value' => htmlspecialchars($row['user_login']))) : $LANG['pm_sender_deleted'], 'read' => ($row['read'])? $TPL->parse('pm/img.tpl', 1, array('src' => HTTP.DOMAIN.PATH.'templates/'.TEMPLATE.'/pic/pm/old.png', 'alt' => $LANG['pm_inbox_old_message_alt'], 'title' => $LANG['pm_inbox_old_message_title'])) : $TPL->parse('pm/img.tpl', 1, array('src' => HTTP.DOMAIN.PATH.'templates/'.TEMPLATE.'/pic/pm/new.png', 'alt' => $LANG['pm_inbox_new_message_alt'], 'title' => $LANG['pm_inbox_new_message_title'])), 'subject' => htmlspecialchars($row['subject']), 'url_pm' => HTTP.DOMAIN.PATH.SCRIPT_FILENAME.'?m=pm&a=inbox_item&id='.$row['id'].SID, 'url_delete' => HTTP.DOMAIN.PATH.SCRIPT_FILENAME.'?m=pm&a=inbox_delete&id='.$row['id'].SID, 'lang_pm_action_delete' => $LANG['pm_action_delete']); } $TPL->block('pm/inbox_body.tpl', 'pm_inbox', $pm_inbox);
Mr.M.I.T. А чё такого в таком подходе? У меня точно такой-же, только выглядет это не так страшно, ну и я ссылки делаю относительные + у меня нету доступа к шаблонам в циклах, за исключением 1-2 мест, где это просто необходимо. PHP: <?php class Guestbook extends ModuleCore { /** * Show guestbook to it's owner with moderation functional * * @return string */ public function show() { $profiles = Core::getInstance('profiles', true); /* @var $profiles Profiles */ $page = $this->utils->getPage($this->core->getArgs(2)); $usr_id = $this->session['auth']['id']; $sql = 'SELECT gsb_usr_id_from, gsb_subject, gsb_id, gsb_msg, DATE_FORMAT(gsb_added, "'.DATE_FORMAT_SQL.'") AS added, DATEDIFF(CURDATE(), gsb_added) AS when_added FROM guestbook WHERE gsb_usr_id_to = '.$usr_id. ' ORDER BY gsb_id DESC'.$this->db->limit($page, $this->per_page); $r = $this->db->query($sql); if ($r && $r->num_rows) { $ids = $rows = array(); while ($row = $r->fetch_assoc()) { $ids[] = $row['gsb_usr_id_from']; $rows[] = $row; } $profiles->preFetch($ids); foreach ($rows as &$v) { $v['gsb_id'] = $this->utils->encode($v['gsb_id']); $v['user'] = $profiles->getUser($v['gsb_usr_id_from']); list($v['added'], $v['when_added']) = $this->utils->getAdded($v['added'], $v['when_added']); $v['gsb_msg'] = nl2br($this->utils->wrap($this->utils->htmlsc($v['gsb_msg']))); $v['gsb_subject'] = $this->utils->wrap($this->utils->htmlsc($v['gsb_subject'])); } unset($v); $sql = 'SELECT COUNT(*) FROM guestbook WHERE gsb_usr_id_to = '.$usr_id; list($total) = $this->db->query($sql)->fetch_row(); $this->parser->set('pager', $this->utils->pager($this->core->joinArgs(1), $total, $page, $this->per_page)); $this->parser->append('guestbook', $rows); } return ($this->box(_("My guestbook"), $this->template('list.htm'))); } } ?> PHP: <form id="postform" method="post"> <?php if (is_set('guestbook')):?> <table id="guestbook" class="tables thumbnails" cellspacing="0"> <?php foreach (get('guestbook') as $val):?> <tr class="row"> <td class="from"><?php echo $val['user']?></td> <td class="message"> <span class="time-block"><span class="subject"><?php echo $val['gsb_subject']?></span> <?php echo $val['added']?></span> <div class="msg"><?php echo $val['gsb_msg']?></div> </td> </tr> <?php endforeach;?> </table> <?php else:?> <div class="hint"><?php echo _("No messages")?></div> <?php endif;?> </form>
короче я сдался. Не могу распарсить вложенные циклы. Смотрел код h2o (можно сказать, что идеал для меня. Те же теги, что и в питоновском Джанго). Так там все как-то разнесено по классам. Такое впечатление, что теги не зависят друг от друга. А у меня гавно какое-то получается.
Koc, дело конечно хозяйское, но считаю, что вложенные циклы - это уже перебор. Трудно представить ситуацию, где без них нельзя обойтись. Кроме того, при громоздких шаблонах и больших количествах циклов, такой шаблонизатор даст тебе просраться по полной, поверь.
вложенные циклы могут использоваться в такой ситуации: прорисовка какой-то таблички, у которой динамическое количество столбцов. Цикл 1 рисует строки, цикл 2 - столбцы. Эта табличка может в админке использоваться например. Первое, что в голову пришло. Да и чего он даст мне просраться? один раз шаблоны компилируются, потом либо в файлы загоняются и инклюдятся либо же в память (apc, eAccelerator) и эвалятся. Да и вообще: будет контроль вложенности
Так уж и один раз? Кеш может сбрасываться часто, ежеминутно. А делать поверх пхп ещё один интерпретируемый язык - это не слишком хорошо, на хайлоаде всё узнаете.
но ведь можно сбрасывать не весь кеш а по тегу (ключу): добавился новый комментарий к описанию отеля (hotel_id=12) $this->cache->removeByPattern('tourust.hotels/comments/12'); изменилась структура страниц $this->cache->removeByPattern('content.menu/:any');
Весь кеш конечно сбрасывать не обязательно, это вовсе самоубийство. Но надо выбирать меньшее из двух зол. В погоне за удобством и изящностью своих конструций, люди часто забывают об ограничениях языка. Можно много чего накрутить в шаблонизатор - вложенные циклы, рекурсия, всевозможные операторы и т.д. В общем, создать ещё одного монстра, который рано или поздно обязательно подведёт.
другой пример того, когда нужны вложенные циклы. Отели, комментарии к отелю. В комментарии может быть список фотографий (пользователь загрузил фотки, когда писал коммент). 1 цикл - вывод комментариев. Условие - есть фотки к комменту или нет. Цикл 2 - вывод этих фоток внутри коммента. Я не буду сильно шаблонизатор нагружать функционалом. Подстановка переменных, циклы, ветвления, наследование, подгрузка шаблонов, комментарии
Вложенные циклы это нормально, бывает что и они нужны. Но, ИМХО, городить очередной Smarty - оно того не стоит. Лучше придумать удобный и лёгкий API для Native шаблонов.
Например мой блог. Есть шаблон статьи, но если она здоровая то полюбому кидаю в кеш ибо парсить ббкоды конечным автоматом долго, да еще и геши в нём подтягивать - ваще капец.
Аа ну тогда да. Хотя по-мойму проще транслировать бб-коды в хтмл при записи в БД, а расцветку задавать стилями.
и, да, я форкаю twig. Еще правда не решил: это будет старый или новый twig. Вчера весь вечер переписывал OOTemplate, так а он без кеша оказался.