• 10488
  • 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
1308

Загрузка...

Комментарии

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

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

Что дал Казахстану переход к трехступенчатой судебной системе?

Что дал Казахстану переход к трехступенчатой судебной системе?

С 1 января 2016 года Казахстан перешел на трехступенчатую судебную систему. Данные изменения действуют уже более 8 месяцев, и в данной публикации мы попробуем разобраться, что это дало Казахстану?
RuSnake
24 сент. 2016 / 11:50
  • 12885
  • 3
В октябре 2016 года состоится VII съезд судей Казахстана

В октябре 2016 года состоится VII съезд судей Казахстана

Проведение съездов судей позволяет принимать стратегические решения по вопросам развития судебной системы и способствует укреплению принципов независимости судейского сообщества.
elawkz
23 сент. 2016 / 13:45
  • 10920
  • 0
О законе законов: Замолвите слово о справедливости

О законе законов: Замолвите слово о справедливости

Акимат г. Астаны предлагал собственнику компенсацию...4 тенге 13 тиын за землю. Потолкуем о справедливости?
mirabeisenova
23 сент. 2016 / 16:39
  • 10672
  • 5
Я –живой пример того, что для начала собственного дела не нужны большие деньги

Я –живой пример того, что для начала собственного дела не нужны большие деньги

Сегодня утром ко мне позвонила тетя и сообщила, что хочет открыть свое дело, но не знает с чего начать и не уверена, хватит ли ей первоначального капитала. Вы не представляете, как она удивилась, когд
toskanbayev_a
21 сент. 2016 / 16:45
  • 10320
  • 28
Кызылорда: перезагрузка, или что изменилось за последние несколько лет

Кызылорда: перезагрузка, или что изменилось за последние несколько лет

В преддверии Дня города мы решили вспомнить, как росла и развивалась наша родная Кызылорда в последние годы. Хотим поделиться своей любовью к родному городу с читателями Юви в этой фотоподборке ...
socium_kzo
22 сент. 2016 / 10:09
  • 6803
  • 8
Сватовство в Казахстане или Заберите скорее мою дочь к себе

Сватовство в Казахстане или Заберите скорее мою дочь к себе

Всю мою сознательную жизнь мне приходилось ходить в гости. В гостях неплохо, не спорю. Бесплатная еда и напитки. В особо продвинутых семьях ещё предоставляются услуги Free Wi-Fi. В особо весёлых...
almatinec_92
23 сент. 2016 / 9:33
25 годовщину независимости от колониального гнета Киргизия встретила вот так...

25 годовщину независимости от колониального гнета Киргизия встретила вот так...

Трехлетний Исхак стал звездой киргизских СМИ и соцсетей на прошлой неделе. Его фотография, спящего на улице среди окурков на картонке, вызвала шок в обществе. В принципе это подобное фото можно...
Shpak
20 сент. 2016 / 15:52
Apple – это уже прошлое. XIAOMI тихо стал настоящим и будущим

Apple – это уже прошлое. XIAOMI тихо стал настоящим и будущим

Безусловно мы все относимся с большим уважением с Стив Джобсу. Но его уже больше 5 лет нет с нами. Бессмысленно продолжать фанатеть от продукции Apple...
GALAN
22 сент. 2016 / 23:19
  • 3726
  • 14
Оралманка из Китая! Надеюсь, ты встретила того, кто по достоинству оценил тебя...

Оралманка из Китая! Надеюсь, ты встретила того, кто по достоинству оценил тебя...

В один прекрасный день я все же подошел к ней и попытался с ней нормально поговорить и пригласить куда-нибудь погулять или поужинать. Мы разговаривали с ней минут 20, я использовал весь свой...
Timurkhan
23 сент. 2016 / 12:26
  • 3448
  • 10