• 11400
  • 120
  • 6
Нравится блог?
Подписывайтесь!

Про Smarty и велосипеды.

Решил написать ответ на пост eudj1n.
Мало кто из кодеров, интересуется "внутренностями" сторонних библиотек, фреймворков и т.д.
Так и я использовал Smarty, и было счастье :) Но природное любопытство взяло своё. Решил посмотреть на Smarty изнутри.
Увидев это огромное количество кода, ничего кроме как "WTF?!" в голову не пришло.
Покапавшись немного в коде, решил что лучше "изобретать велосипеды, чем ездить на тракторах" (c).

Написали с коллегой (p0is0n) маленький шаблонизатор NanoTpl.


<?
final class Tpl
{
 
    private static $vars, $globals;
 
    private static $buffer = '';
 
    public static $tpl;
 
    /**
* Добавление переменной в локальный шаблон
*
* $name - имя переменной
* $value - значение
* $replace - флаг, если установлен в значение отличное от нуля переменная будет перезаписана
*
* @param string $name
* @param string $value
* @param bool $replace
*/

    public static function assign($name, $value, $replace = false)
    {
        if (isset(self::$vars[$name]) and ! $replace)
        {
            if(is_array(self::$vars[$name]) && is_array($value))
                self::$vars[$name]=array_merge(self::$vars[$name],$value);
            elseif(is_array(self::$vars[$name]))
                self::$vars[$name][]=$value;
            else
                self::$vars[$name] .= $value;
        }
        else
            self::$vars[$name] = $value;
    }
    /**
* Добавление глобальной переменной (будет доступна во всех шаблонах)
*
* $name - имя переменной
* $value - значение
* $replace - флаг, если установлен в значение отличное от нуля переменная будет перезаписана
*
* @param string $name
* @param string $value
* @param bool $replace
*/

    public static function assignGlobal($name, $value, $replace = false)
    {
        if (isset(self::$globals[$name]) and ! $replace)
        {
            if(is_array(self::$vars[$name]) && is_array($value))
                self::$vars[$name]=array_merge(self::$vars[$name],$value);
            elseif(is_array(self::$vars[$name]))
                self::$vars[$name][]=$value;
            else
                self::$globals[$name] .= $value;
        }
        else
            self::$globals[$name] = $value;
    }
    /**
* Обработка шаблона , результат будет записан в переменную $content (используется при отображении главного шаблона)
*
* $tpl - имя шаблона
* $global - использовать глобальные переменные
*/

    public static function compile($tpl = null, $global = false)
    {
        $tmp = self::fetch($tpl, $global);
        if ($tmp)
        {
            self::$buffer .= $tmp;
        }
    }
    /**
* Обработка шаблона , возвращает html
*
* $tpl - имя шаблона
* $global - использовать глобальные переменные
*/

    public static function fetch($tpl = null, $global = false)
    {
        $out = '';
        if (null !== $tpl)
            self::$tpl = $tpl;
        if (is_readable(TPL_DIR . DIRECTORY_SEPARATOR . self::$tpl) and is_file(TPL_DIR . DIRECTORY_SEPARATOR . self::$tpl))
        {
            if (! is_array(self::$vars))
                self::$vars = array();
            if ($global)
            {
                if (is_array(self::$globals) and ! empty(self::$globals))
                    self::$vars += self::$globals;    
            }
            if (! empty(self::$vars))
            {
                foreach (self::$vars as $k => &$v)
                {
                    $$k = $v;
                }
                self::$vars = array();
            }
            $level = error_reporting();
            error_reporting(E_ALL);
            ob_start();
            include(TPL_DIR . DIRECTORY_SEPARATOR . self::$tpl);
            $out = ob_get_contents();
            ob_end_clean();
            error_reporting($level);
            self::$tpl = null;
        }
        else
        {
            trigger_error('template "' . self::$tpl . '" not found', E_USER_WARNING);
        }
        return $out;
    }
    /**
* Отображает шаблон
*
* $tpl - имя шаблона
*/

    public static function display($tpl="main.tpl")
    {
        self::assign('content', self::$buffer);
        self::$buffer = self::fetch($tpl, true);
        self::$globals = array();
        print self::$buffer;
    }
 
}
?>

Мал по размерам, быстро работает.Всегда готов к работе)) Приведу здесь небольшое сравнение Smarty и NanoTpl.
Smarty
<?php
require('class/Smarty.class.php'); //подключаем класс
$smarty = new Smarty(); //создаем экземпляр
$smarty->template_dir = '/web/www.domain.com/smarty/templates'; //директория с шаблонами
$smarty->compile_dir = '/web/www.domain.com/smarty/templates_c'; //тут "скомпилированные" шаблоны
$smarty->cache_dir = '/web/www.domain.com/smarty/cache'; //кеш
$smarty->config_dir = '/web/www.domain.com/smarty/configs'; //еще дирректория :)
$tags = array('php','Smarty','шаблонизатор'); //создаём массив
$smarty->assign('name','eudj1n'); //передаём в шаблон данные
$smarty->assign('tags',$tags);
$smarty->display('main.tpl'); //отображаем главный шаблон
?>

Сам шаблон


Smarty


//передадим привет eudj1n-у. :)
Hello, {$name}!
//отобразим значения массива
{foreach from=$tags item=tag}
{$tag}
{/foreach}


NanoTpl
<?php
require('class/Tpl.class.php'); //подключаем класс
define('TPL_DIR', ROOT_DIR . DIRECTORY_SEPARATOR . 'tpl'); //определяем константу - дирректория где лежат наши шаблоны
$tags = array('php','Smarty','шаблонизатор'); //передаём в шаблон данные
Tpl::assign('name','eudj1n');
Tpl::assign('tags',$tags);
Tpl::display(); //показываем всем главный шаблон по-умолчанию подгружается "main.tpl"
?>
Сам шаблон


Smarty


//передадим привет eudj1n-у. :)
Hello, <?=$name?>!
//отобразим значения массива
foreach ($tags as $tag){?>
<?=$tag?>
<?}?>

Как видите NanoTpl прекрасно справляется со своей работой. И работа с ним ничють не сложнее чем со Smarty.
Многие наверно сейчас скажут, что использовать php в шаблонах - зло. Т.к. можно писать туда всё что хочешь (запросы к бд и т.д.)
Кстати и разработчики Smarty используют это, как плюсик в безопасности шаблонизатора:
"Security: Templates do not contain PHP code.Therefore, a template designer is not unleashed with the full power of PHP, but only the subset of functionality made available to them from the programmer (application code.)"
Но стоит ли жертвовать производительностью в пользу такой сомнительной "безопасности"?
Вы можете существенно доработать NanoTpl под свои нужды, т.к. он только и умеет что передавать данные в шаблон.
Хочу еще раз сказать: небойтесь изобретать велосипеды. Делая это вы несомненно приобретёте опыт и возможно ваш велосипед будет лучше чем соседский :)
NeD
11 июля 2008, 16:27
1391

Загрузка...
Loading...

Комментарии

eudj1n
0
0
дада, и Вам привет от меня :)

Вопрос - мне нужно накопить некоторые данные, потом собрать их вместе и вывести своей функцией - в случае с Вашим классом придется print менять на return.

Как вариант - можно добавить ещё один входной параметр в функцию display(), который и будет отвечать за вывод/возвращение результата обработки.
eudj1n
0
0
упс. спасибо, не доглядел.
Надо хоть немного поизучать предмет прежде чем задавать вопрос
eudj1n
0
0
ок, более развернутый каммент после подробного изучения сабжа.
eudj1n
0
0
1) У топика столько плюсов - но никто не отписался, что в исходниках шаблона не хватает кое-чего :) а именно:

<? перед foreach ($tags as $tag){?>

2) Зачем к константе TPL_DIR кроме директории, присваивать ещё и расширение '.tpl'? Не смог заставить класс обрабатывать шаблон пока не убрал это самое расширение и не прописал абсолютный путь к директории.

3) Код шаблона копировал как есть (то есть с коментариями), при компиляции - опа, они на экране. Может заведомо убирать их из вывода?

Итог такой - без напильника не обойтись :) Лично для меня не хватает возможностей, да, согласен - можно переписать кое-что, а кое-что добавить. Но я останусь верным сабжу моего топика, а возможно, если будет время - напишу что-нибудь свое. Но пока в этом нет необходимости.
eudj1n
0
0
насчет второго вопроса все понял, шаблоны должны лежать в root/tpl.
NeD
0
0
1. Опечатался.
3. Комментарии само собой надо убрать.
Все недочёты которые Вы указали, являются следствием моей невнимательности. Приведите пример чего Вам нехватает?
eudj1n
0
0
1) блоки
2) кэширование

Что касается блоков (буду приводить аналогии с XTemplate) - у меня есть главный шаблон (main.xtpl), в котором находится абсалютно весь хтмл-код сайта. В нужных местах я обрабатываю и вывожу нужный мне блок, при этом все остальное остается не тронутым (и соответственно не выводится). Для меня это удобней, т.к. нет необходимости шаблон раскидывать по куче файлов. При этом, сам шаблон выглядит как обычный хтмл-файл, за исключением обозначения переменных и блоков.

Что касается кэширования - думаю и так все ясно.
1.Блоки это лично ваше предпочтение. Это как ООП против функционального программирования. Каждый пользуется тем, чем ему удобнее. Нравится ииспользовать блоки - используйте. Я не кого не пытаюсь убедить использовать NanoTpl.
2.Кэшировать нужно сами данные, а не готовые html странички. Тут "кэш", как в Smarty или в других шаблонизаторах не нужен.В шаблонах находится php код. Smarty и другие шаблонизаторы используют свой код, который необходимо распарсить и перевести в php. Их "кэш" - это всего лишь обработанный шаблон.
Darmen
0
0
Неплохо, но давайте взглянем на код шаблона глазами человека, далекого от шаблонизаторов, но знакомым с азами PHP.
ЧТО он видит? Код на PHP. Никакой разницы ;)
NeD
0
0
а есть ли большая разница с кодом Smarty?
AXE
0
0
Ой да ну... Лучше ездить на тракторах, они не застрянут.
Вообще, можно просто html выделить в отдельный файл в отдельной директории. И там, среди html-кода использовать конструкции:
while (...):

endwhile;

И всем удобно:))
lEx0kz
0
0
вообще я за шаблонизаторы, но мне не нравится монстроузность Смарти, активно работал с ним когда то. кеширование есть, но все равно ждало мег-полтара памяти и чуть процессороного времени. так что я за чистый код. пишу для себя и не вижу толку от использования шаблонизатора. (юзаю в основном codeigniter)
mobman
0
0
Зачем все статикой сделано?

Оставьте свой комментарий

Спасибо за открытие блога в Yvision.kz! Чтобы убедиться в отсутствии спама, все комментарии новых пользователей проходят премодерацию. Соблюдение правил нашей блог-платформы ускорит ваш переход в категорию надежных пользователей, не нуждающихся в премодерации. Обязательно прочтите наши правила по указанной ссылке: Правила

Также можно нажать Ctrl+Enter

Популярные посты

СМИ – ассистент провокаторов? Как гости из соседних стран сеют раздор в Казахстане

СМИ – ассистент провокаторов? Как гости из соседних стран сеют раздор в Казахстане

Инцидент с пьяным киргизским гостем на борту Air Astana, наверное, остался бы только во внутренних сводках авиакомпании, если бы г-н Доган, не поднял громкий крик о государственном языке.
openqazaqstan
17 авг. 2017 / 14:43
  • 11875
  • 177
Дайте Байбеку сломать и переделать город. Он хочет шагнуть вверх, а не бабло украсть

Дайте Байбеку сломать и переделать город. Он хочет шагнуть вверх, а не бабло украсть

Я в тогдашней Алма-Ате родился, вырос. В школу начал ходить пешком. Весь центр опползал. Все эти знаковые места помню как ещё не знаковые места. Никаких этих ностальгических страданий у меня нет.
Aidan_Karibzhanov
21 авг. 2017 / 16:25
  • 4853
  • 29
Казахский национализм раньше выглядел несовременно. Теперь он другой

Казахский национализм раньше выглядел несовременно. Теперь он другой

Националисты стали совсем другими. По-английски хорошо говорят, русскую классику цитируют. Очень современные, образованные, адекватные. А после Крыма в националисты уже чуть ли не любой казах готов был записаться.
Aidan_Karibzhanov
16 авг. 2017 / 16:52
Имеющий уши да услышит. Латиница касается только казахского языка

Имеющий уши да услышит. Латиница касается только казахского языка

Президент Назарбаев наконец-то разъяснил для всех, кто ещё не понял, очевидный вопрос, который всем в Казахстане очевиден. Елбасы повторил: на латиницу мы переводим казахский язык, и это не означает отказ от русского языка.
openqazaqstan
18 авг. 2017 / 16:23
  • 3460
  • 52
Подземная Акмечеть Бекет-Ата в Атырауской области – одно из самых сакральных мест

Подземная Акмечеть Бекет-Ата в Атырауской области – одно из самых сакральных мест

Его отцом был Мырзагул, матерью Жания, оба глубоко верующие. По рассказам, Бекет-Ата обладал богатырской силой, что в том числе помогало выбивать мечети в крепких скалах.
theYakov
21 авг. 2017 / 17:21
  • 2491
  • 3
«Доехать до Алтын Орды» – как мошенники обманывают алматинцев

«Доехать до Алтын Орды» – как мошенники обманывают алматинцев

Из множества грустных откровений постепенно сложился перечень самых распространённых уловок охотников за нашими деньгами. В нём ожидаемо лидировали профессиональные попрошайки.
caravan_kz
16 авг. 2017 / 15:05
  • 2362
  • 4
Надо научиться видеть скрытые экономические процессы за вспышкой национального гнева

Надо научиться видеть скрытые экономические процессы за вспышкой национального гнева

При полном отсутствии бюджетного жилищного строительства, целые аулы оседают в ветхих домишках, сквозь заборы которых насмешливо возвышаются башни "коктемов", "риц карлтонов" и "есентаев".
niyazov
19 авг. 2017 / 11:16
  • 2515
  • 67
В Кокшетау строят два парка для молодёжи. Будут учтены интересы и любителей спорта

В Кокшетау строят два парка для молодёжи. Будут учтены интересы и любителей спорта

Общая площадь парка составляет 25 гектаров. На территории предусмотрено устройство прогулочных дорожек, площадок для установки аттракционов и павильонов различного назначения, цветников.
zhasakmola
17 авг. 2017 / 17:13
  • 2162
  • 1
«Нас и здесь неплохо кормят», или почему я не собираюсь уезжать из Казахстана

«Нас и здесь неплохо кормят», или почему я не собираюсь уезжать из Казахстана

Я всегда теряюсь, когда слышу этот вопрос, потому что я так и не сумел выразить причину одной фразой. Давайте рассмотрим популярные варианты, и я объясню, что именно мне в них не нравится.
convoluted
21 авг. 2017 / 12:29