Шаблонный движек тем Smarty

23 июля 2012 - Dream
 Сайт проекта Smarty – ссылка.

Полный список команд Smarty описан по ссылке на русском языке.

Установка (в инстанте он уже в комплекте).

 

Для начала нужно скачать архив со смарти с официального сайта и распаковать его. Там есть папка libs, которую я скопировал в одну директорию со своим файлом index.php, в котором я буду ставить эксперименты. Эту папку libs я для удобства переименовал в smarty. Эта папка содержит две папки plugins и internals, а еще она содержит 4 файла: Config_File.class.php, Smarty.class.php, Smarty_Compiler.class.php, debug.tpl.

Из них нас будет интересовать только Smarty.class.php.

Кстати, в смарти есть возможность написания плагинов (как вы уже догадались по папке plugins). Эту возможность мы рассмотрим отдельно в следующих статьях. А пока просто познакомимся с основными возможностями.

Теперь нам нужно создать папку с именем templates_c (туда smarty будет сваливать промежуточные файлы в процессе построения страниц по шаблонам) в папке smarty. Еще создадим папку templates (в ней будем содержать шаблоны) в корне нашего «проекта».

Привет Мир через смарти

Для начала просто выведем содержимое шаблона в окно браузера без использования всяких переменных и т.п.:

index.html

<html>

<head>
    <title>Title</title>
</head>

<body>
Hello, World!
</body>

</html>

index.php

<?
    include 'smarty/Smarty.class.php';
    
    $smarty = new Smarty;
    $smarty->compile_dir  = 'smarty/templates_c';
    $smarty->template_dir = 'templates';
    
    $smarty->display('index.html');
?>

Только сделаю одно замечание: файл index.html должен лежать в директории templates! Здесь мы использовали функцию display для вывода шаблона, а могли бы fetch:

echo $smarty->fetch(‘index.html’);

Эффект был бы тот же самый, просто во втором случае результат интерпретации шаблона возвращается функцией (можно присвоить переменной), а не выводится в окно браузера.

Работаем с переменными

Теперь сформируем ту же страничку, но с использованием переменных:

index.html

<html>

<head>
    <title>{$title}</title>
</head>

<body>
{$body}
</body>

</html>

index.php

<?
    …

    $smarty->assign('title', 'Title');
    $smarty->assign('body', 'Hello, World!');
    
    $smarty->display('index.html');
?>

Как видите, здесь мы присвоили переменным title и body свои значения. Мы сделали это двумя вызовами метода assign, но могли бы обойтись и одним:

$smarty->assign(Array(‘title’ => ‘Title’, ‘body’ => ‘Hello, World!’));

Кстати, присвоенные значения переменных можно удалить:

<?
    …

    $smarty->assign(Array('title' => 'Title', 'body' => 'Hello, World!'));
    $smarty->clear_all_assign();
    
    $smarty->display('index.html');
?>

В этом случае будет выведена страничка с пустым заголовком и телом.

Можем еще очистить конкретную переменную, а не все: $smarty->clear_assign(‘title’).

Если нам вдруг понадобится определить в самом скрипте значение присвоенной Smarty переменной, мы это сможем сделать следующим образом:

echo $smarty->get_template_vars('title'); // определяем значение переменной $title
$array = $smarty->get_template_vars();  // определяем значения всех переменных:
echo 'title: '.$array['title'];
echo 'body: '.$array['body'];

Интересно, а что будет, если мы одной и той же переменной присвоим разные значения?

$smarty->assign('title', 'Title1');
$smarty->assign('title', 'Title2');

У меня в этом случае заголовок страницы получился «Title2». А если я хочу присвоить одной и той же переменной два разных значения? Ну это уже тогда массив получается. Но это можно сделать в Smarty:

$smarty->append('title', 'Title1');
$smarty->append('title', 'Title2');

Теперь заголовок страницы будет «Array». Smarty понял, что это массив и сказал нам об этом английским словом. А мы этот массив должны разобрать.

Работа с массивами и циклами

Сейчас наша конкретная задача – вывести несколько заголовков (разделенных запятыми), которые запрятаны в переменной $title – в массиве:

index.html

<html>

<head>
    <title>
    {foreach from=$title item=titem name=titles}
        {$titem}
        {if not $smarty.foreach.titles.last}
        ,
        {/if}
    {foreachelse}
        No title
    {/foreach}
</title>
</head>

<body>{$body}</body>

</html>

index.php

<?
    …

    $smarty->assign('title', 'Title1');
    $smarty->append('title', 'Title2');
    $smarty->assign('body', 'Hello, World!');

    $smarty->display('index.html');
?>

О, как! Сразу несколько возможностей пришлось рассмотреть. Во-первых, получаем доступ к массиву с помощью foreach. Во-вторых, применяем механизм условий: если выводится последний заголовок, то не ставить после него запятую. В-третьих, если массив $title пустой, выводим «No title».

Сам блок итераций foreach мы обозвали «titles» с помощью атрибута name. Это нужно, чтобы заиметь доступ к свойствам каждой итерации через $smarty.foreach.titles:

index – содержит индекс текущей итерации (начиная от 0)
iteration – то же самое, что и index, но отсчет начинается от 1
first – содержит TRUE, если текущая итерация первая
last – содержит TRUE, если текущая итерация последняя
total – содержит количество итераций

Поставленную задачу выполнили. Теперь немного усложним ее – сделаем то же самое, но с использованием ассоциативных массивов в качестве переменных (вложим массив в массив):

index.html



<title>
    {foreach from=$title item=titem name=titles}
        {$titem.title} - {$titem.number}
        {if not $smarty.foreach.titles.last}
            ,
        {else}
        {/if}
    {/foreach}
</title>

index.php

<?
    …

    $titles = Array();
    $titles[] = Array('title' => 'Title', 'number' => 1);
    $titles[] = Array('title' => 'Title', 'number' => 2);
    
    $smarty->assign('title', $titles);
    $smarty->assign('body', 'Hello, World!');

    $smarty->display('index.html');
?>

Пример выведет следующий заголовок страницы: Title – 1, Title – 2

Это хорошо конечно, – скажете Вы, – но как вывести массив наоборот? А я отвечу – для этого используется {section}:

index.html



<title>
    {section loop=$title name=titles step=-1}
        {$title[titles].title} - {$title[titles].number}
        {if not $smarty.section.titles.last}
            ,
        {else}
        {/if}
    {/section}
</title>

Теперь заголовок у нас обратный: Title – 2, Title – 1

Кстати, {section} можно использовать и без массива. Например – нам нужно вывести числа от 1 до 12 – месяцы:



<body>
{section name=month start=1 loop=13 step=1}
    {$smarty.section.month.index}<br />
{/section}
</body>

Или то же самое можно было сделать с использованием {counter}:

{counter start=1}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}

Только первый вариант гораздо компактнее.

Ах, да. Я еще забыл сказать, что в foreach, section, if и т.п., т.е. любые блоки могут содержать что угодно и быть вложенными. Главное – соблюдать очередность открытия и закрытия тегов. Например, могут быть вложенные циклы и условия: цикл-цикл, условие-условие, цикл-условие и т.д.

 

Условия в смарти

Как вы уже поняли из предыдущей статьи, смарти обладает своими тегами. Теги условий выглядят следующим образом:

{if $a &gt; $b}
B is less than A
{/if}

Это простое условие. Теперь простое ветвление:

{if $a &gt; $b}
B is less than A
{else}
A is less than or equal to B
{/if}

 

Но наверно во всех языках программирования есть конструкция elseif – не обделили ею и Smarty:

{if $a &gt; $b}
B is less than A
{elseif $a &lt; $b}
A is less than B
{else}
A is equal to B
{/if}

Кстати, вместо знаков <,>,==, !=, <=, >=, !, % можно использовать соответственно lt, gt, eq, ne, lte (le), gte (ge), not, mod. Т.е. последний пример можно записать так:

{if $a gt $b}
B is less than A
{elseif $a lt $b}
A is less than B
{else}
A is equal to B
{/if}

В условиях еще можно использовать логические выражения: or (||), and (&&) и т.п. Вот например:

{if $a &gt; $b or $a &lt; $b}
A is not equal to B
{/if}

Можно использовать скобки (для повышения приоритета логической операции): {if ($a > $b or $a < $b) and $a < $c && $a < $d}{/if}

Что меня удивило в условиях, так это возможность проверять числа на четность-нечетность и делимость на некоторые числа (подозреваю, что эти операции сделаны через mod):

{if $num is even}{$num} – четное число{else}{$num} – нечетное число{/if}
{if $num is not even}{$num} – нечетное число{else}{$num} – четное число{/if}
{if $num is odd}{$num} – нечетное число{else}{$num} – четное число{/if}
{if $num is div by 5}{$num} делится на 5 без остатка{/if}
{if $num is not div by 5}{$num} не делится на 5 без остатка{/if}

Каждый программер прекрасно знает, что проверить четность можно с помощью операции деления по модулю 2:

{assign var='num' value=100}
{if $num mod 2 eq 0}{$num} - четное число {/if}

Работа с переменными в шаблоне

Кстати, вот тут я использовал директиву assign для присвоения переменной значения в шаблоне. Интересно, а как быть, если нам нужно прибавить к переменной какое-то числовое значение?

Я пробовал {assign var=’num’ value=100+1}, но видимо это неправильно. Ок, тогда попробуем так:

{assign var=num value=101}
{assign var=num value=$num+1}
{if $num mod 2 eq 0}{$num} - четное число {/if}

Сработало! То же самое можно проделать с любой арифметической операцией.
Хорошо, с числами понятно. А как насчет строк?

Попробуем соединить две строки в одну. С помощью assign у меня не получилось и я начал искать функцию, которая смогла бы это сделать. Оказывается в smarty есть полный аналог php-функции sprintf для форматирования строк:

{assign var='world' value='world'}
{assign var='str' value=$world|string_format:'hello, %s'}
{$str}

Этот пример выведет знакомую до боли всем фразу. Этот же пример можно было укоротить:

{assign var='world' value='world'}
{$world|string_format:'hello, %s'}

Работа со строками

Ну раз уж мы перешли к строкам, тогда посмотрим, что вообще с ними можно сделать в смарти. Я скажу одно – можно сделать все, что можно сделать в php:

  • Сделать первую букву заглавной: {$str|capitalize}
  • Присоединить одну строку к другой: {$str|cat: $str2} – кстати, замена рассмотренному выше с string_format варианту
  • Подсчитать количество символов: {$str|count_characters:true}
  • Подсчитать количество абзацев: {$str|count_paragraphs}
  • Подсчитать количество предложений: {$str|count_sentences}
  • Подсчитать количество слов: {$str|count_words}
  • Поставить отступ перед строкой: {$str|indent}
  • Сделать все буквы в строке строчными: {$str|lower}
  • Сделать все буквы в строке прописными: {$str|upper}
  • Аналог php-функции wordwrap для разбиения длинных предложений: {$str|wordwrap}
  • и т.д.

Вот например интересная возможность есть. Допустим у нас есть очень длинная строка, которая не помещается в ограниченную ячейку таблицы. Что мы можем сделать в этом случае? Мы можем обрезать эту строку, да так, чтобы в конце стояло, например, многоточие:

{assign var='str' value='Оооочень длинная строка. Ну просто ооооооооооооооочччччееень длииииииинная'}
{$str|truncate:30}

Выведет:
Оооочень длинная строка. Ну…

Этим мы сказали смарти, чтобы он обрезал строку, оставив в ней 27 символов и многоточие в конце (27+3=30). Если мы хотим вместо трех точек поставить что-нибудь свое или вообще ничего не ставить:

{$str|truncate:30:"==="}
{$str|truncate:30:""}

Выведет:
Оооочень длинная строка. Ну===
Оооочень длинная строка. Ну пр

Эти три точки можно поставить и в середине строки:

{$str|truncate:30:'…':true:true}

Выведет:
Оооочень длинн… длииииииинная

Или вот еще очень полезная вещь. Допустим у нас есть какая-то переменная, которая может быть инициализирована в php-скрипте с помощью $smarty->assign. Но она же может быть и неинициализирована (пустая). Тогда в шаблоне выводить будет нечего. Но вместо пустоты иногда требуется все-таки вывести какую-то строку. Можно было бы конечно написать, например, так:

{if $str}
{$str}
{else}
No information
{/if}

Но гораздо компактнее вот так: {$str|default:’No information’}. Вместо строки с кавычками может быть переменная: {$str|default:$noinfo}.

Ага.. Нашел еще одну очень полезную вещь – обфускация email. Допустим, нам нужно вывести email, но чтобы пользователь видел его, а спаммерский скрипт, который ищет email-адреса на странице, не смог его определить (или затруднить ему определение). Рассмотрим несколько примеров:

{mailto address=”some@mail.ru”}
<a href=”mailto:some@mail.ru”>some@mail.ru</a>

{mailto address=”some@mail.ru” text=”мой ящик”}
<a href=”mailto:some@mail.ru”>мой ящик</a>

{mailto address=”some@mail.ru” text=”мой ящик” encode=”javascript”}
<script type=”text/javascript”>eval(unescape(‘%64%6f%63%720%ff%f9%e8%ea%3c%2f%61%3e%27%29%3b’))</script>

Тут уже сложнее понять, что за адрес скрывается в этой куче шестнадцатеричных чисел, мягко говоря icon smile Смарти: продолжаем осваивать

На самом деле все рассмотренные (и еще много нерассмотренных) функции – не что иное, как плагины, которые расширяют функциональность smarty. Мы с вами тоже научимся их писать, только не в этой статье, а чуть позже.

Комментарии

Эх, что-то я совсем забыл про комментарии в Smarty icon smile Смарти: продолжаем осваивать Надо было про них в первой статье рассказать. Ну ладно, лучше поздно, чем никогда:

{* Это однострочный комментарий *}

{* Это
многострочный
комментарий *}
Вот, наверстал упущенное icon smile Смарти: продолжаем осваивать

Глобальная переменная $smarty

Во всех шаблонах можно использовать переменную $smarty. Она дает доступ к следующим глобальным массивам вызвавшего шаблон скрипта:

  • $_GET, $_POST, $_REQUEST ($smarty.get, $smarty.post, $smarty.request)
  • $_COOKIE ($smarty.cookie)
  • $_SERVER ($smarty.server)
  • $_ENV ($smarty.env)
  • $_SESSION ($smarty.session)

Например, получим содержимое переменной $_REQUEST['id']: {$smarty.request.id}

Или определим имя скрипта: {$smarty.server.SCRIPT_NAME}

Кроме этого можно узнать текущее время: {$smarty.now} – возвращает количество секунд, прошедших с 1 января 1970 года. Это аналог php-функции timestamp (вообще, аналогами их называть неправильно, потому что на самом деле эти php-функции и вызываются; скорее – эквиваленты). Вывести текущее время можно с помощью модификатора date_format (эквивалент одноименной php-функции):

{$smarty.now|date_format:’%Y-%m-%d %H:%M:%S’}

С помощью $smarty.const можно получить доступ к любой константе вызвавшего скрипта, которая была объявлена с помощью define:

{$smarty.const.MY_CONST}

Ну и ради интереса можно посмотреть текущую версию Smarty: {$smarty.version}. У меня вывелось 2.6.18.

http://i-novice.net

 

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

ДокументацияПеременные Smarty

Рейтинг: 0 Голосов: 0 5550 просмотров
Комментарии (0)

Нет комментариев. Ваш будет первым!