Как сделать собственный шаблонизатор

Рано или поздно у каждого программиста возникает желание написать свой Smarty :) .
Называются разные аргументы - более быстрый, гибкий, удобный и так далее.

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

И тут все сразу смотрят в сторону eval. Первое, что приходит в голову - написать eval(file_get_contents('template.htm')). И, конечно же, это не работает. Потом читается документация и пишется что-то вроде eval('echo("'.file_get_contents('template.htm').'");');. Но и это тоже не работает.

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

Например, чтобы

HTML:
  1. <head><title>{=$title}</title></head>
  2. <body>{=$content}</body>
  3. </html>

превратилось в

HTML:
  1. <head><title>My homepage</title></head>
  2. <body>Under construction</body>
  3. </html>

можно написать такую простенькую функцию.

PHP:
  1. <?php
  2.  
  3. function parsePage($params=array(), $template='main.tpl') {
  4.     ob_start(); // echo to buffer, not screen
  5.     include($template);
  6.     $html = ob_get_clean(); // get buffer contents
  7.    
  8.     foreach ($params as $key=>$value) {
  9.         $html = str_replace('{=$'.$key.'}', $value, $html);
  10.     }
  11.    
  12.     return $html;
  13. }
  14.  
  15. $params = array('title'=>'My homepage', 'content'=>'Under construction');
  16. $html = parsePage($params);
  17. echo($html);
  18.  
  19. ?>

Преимущество в том, что работает очень быстро, кода мало, верстальщикам можно объяснить суть шаблонов за пару минут.

Если вы знаете, как сделать шаблонизатор ещё проще - расскажите.


Понравилось?

  1. Подпишись через RSS
  2. Расскажи о http://php.southpark.com.ua друзьям.
    Все способы хороши: ICQ, E-mail, свой блог, комментарий в чужом блоге или сообщение на форуме
  3. Добавь статью на news2.ru, Хабрахабр или в закладки

Огромное спасибо!

Похожие статьи

И не стесняйтесь комментировать - у меня стоит плагин, который убирает rel="nofollow" у людей, которые написали больше 5 комментариев.

RSS feed | Trackback URI

19 комментариев »

Comment by Влад
2008-01-28 20:14:57

Однако, велосипед :)

Вот, здесь, например.. Датировано 2003 годом :)

http://spectator.ru/technology/php/easy_templates

2008-01-28 20:27:12

Да, ту статью помню. Кажется, пару лет назад её читал, когда делал свой фреймворк.

Но это не совсем то. Была задача сделать именно с параметрами {=$title}, а не < ?=$title?> (нужна совместимость с шаблонами определённой CMS).
В указанной статье нет упоминания об ob_*, а это важно, так как даёт определённую свободу, если надо делать более сложные шаблоны с вложениями и другой чепухой.
Я сам в большинстве случаев за шаблоны на PHP, но ведь даже в Хабре решили от них отказаться. Что-то знают... :)

 
 
Comment by Danaki
2008-01-28 23:51:02

А вот как Смарти прикрутили не подходит? http://bakery.cakephp.org/articles/view/how-to-use-smarty-with-cake-smartyview

2008-01-29 00:50:04

Идея в том, чтобы создать простейший шаблонизатор, который будет настолько лёгким, насколько можно, потому что непонятно, где он будет работать.
Единственным требованием должно быть только наличие PHP.
А у CakePHP есть неплохие требования по памяти, да ещё и базу данных ему подавай :)

При этом бонусное требование - понятность для верстальщиков, которые не знают, что такое PHP; совместимость с какой-то странной CMS в которой они привыкли работать.
Поэтому Smarty тоже не подходит.

 
 
Comment by Sam Subscribed to comments via email
2008-01-29 13:03:22

Smarty будет работать быстрее с его предкомпиляцией ;)

 
Comment by Revisor
2008-02-14 17:27:51

Так, как на этом сайте принято замечать даже мелкие неточности, то код метода нужно написать так:

function parsePage($params=array(), $template='main.tpl') {
ob_start(); // echo to buffer, not screen
include($template);
$html = ob_get_clean(); // get buffer contents

foreach ($params as $key=>$value) {
$html = str_replace('{=$'.$key.'}', $value, $html);
}
return $html;
}

2008-02-15 17:30:19

ничего себе мелочь - забыл return сделать :shock:
исправил, спасибо

 
 
Comment by Виктор Subscribed to comments via email
2008-02-23 19:02:27

Дан шаблон main.tpl:

{=$var1}
{=$var2}

'hack {=$var2} motherfuck',
'var2' => 'ha-ha'
);
parsePage($vars);

?>

2008-02-23 23:33:44

Конечно же, то, что в include нельзя доверять менять пользователям, только обученым людям.
Тогда, это не баг, а фича :grin:

 
 
Comment by Hokage
2008-03-03 01:53:41

Ошибка:
str_replace('{=$'.$key.'}', $value, $html);
А нужно:
$html = str_replace('{=$'.$key.'}', $value, $html);

2008-03-06 10:08:56

Спасибо. Видимо, нельзя писать в блог в конце рабочего дня - сплошные глюки.

 
 
Comment by Hokage
2008-03-03 16:42:30

Помоему ошибка:
str_replace('{=$'.$key.'}', $value, $html);
А надо:
$html = str_replace('{=$'.$key.'}', $value, $html);

 
Comment by Yaroslav Vorozhko Subscribed to comments via email
2008-03-11 16:15:42

Велосипед... :???:
Так однозначно быстрее
//template bla.phtml

PHP и есть шаблонизатор, причем самый быстрый и самый гибкий из всех написанных . :mrgreen:

 
Comment by Виктор Subscribed to comments via email
2008-03-11 18:00:41

Это холивар, кому как.

 
Comment by Владимир Subscribed to comments via email
2008-04-18 00:40:06

И тут все сразу смотрят в сторону eval. Первое, что приходит в голову - написать eval(file_get_contents('template.htm')). И, конечно же, это не работает. Потом читается документация и пишется что-то вроде eval('echo("'.file_get_contents('template.htm').'");');. Но и это тоже не работает.

Мы в своих шаблонах используем eval, не не та как вы описали:

например есть файл file.tpl:

{$main}

</html

И мы делаем так:

$main = "ou la la :-)";
$template = @file_get_contents('file.tpl');
$t = '';
@eval("\$t=<<<HTML\n{$template}\nHTML\n;");

Потом, в нужном месте делаем: echo $t;
Даже не нужно включать буфферизацию вывода ))

естественно, это упрощённый вариант. наш код оформлен в целый класс, где есть условия, циклы, компилирование шаблонов :-)

2008-04-21 17:32:34

признаюсь, я очень боюсь конструкций с @ и eval.
стараюсь их использовать только в самом-самом крайнем случае и то если уверен, что сам контролирую то, что эвалится.

 
 
Comment by Сеня Subscribed to comments via email
2008-05-17 06:40:03

.....я конечно извиняюсь...НО....как в этом шаблоне проделывать фокусы с использованием

do{}
While()

или

For()
куда я только не вписывл...и как только не пробывал....что-то не то получалось.
подскажите.....а
Заранее спасибо

2008-05-19 09:53:14

Никак. Это не баг, а фича :)
Если нужно использовать управляющие конструкции PHP, то нужно пользоваться CakePHP и его шаблонами.

 
 
Comment by Jeurey
2008-06-17 03:20:37

Ну зачем сразу чужие шаблоны? Использовать MVC можно и без таких вещей... Если нужен цикл - используем 1 шаблон (который описывает отображение элемента) и оборачиваем во враппер (тобишь - другой шаблон).

И код от шаблона отделен, и функционал реализован ;)

 
Имя (required)
E-mail (required - never shown publicly)
URL
Текст комментария
You may use <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> in your comment.