Смарти. Введение
Продолжаем тему шаблонизаторов и сегодня рассмотрим наверно самый популярный из них - Smarty (Смарти). Точнее даже не рассмотрим, а начнем рассматривать, потому что у смарти довольно мощный движок, все возможности которого рассмотреть в одной статье думаю нереально. |
Сайт проекта Smarty - [ссылка].
Вот думаю, с чего бы начать…
Ага. Начну-ка с установки. Я еще недавно рассматривал другой шаблонизатор Blitz в этой статье. Так вот, там я писал, что его нужно ставить как отдельное расширение PHP. Теперь спешу всех успокоить: смарти не обладает таким недостатком, поэтому его можно использовать в любом проекте.
Для начала нужно скачать архив со смарти с официального сайта и распаковать его. Там есть папка 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
<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
<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 переменной, мы это сможем сделать следующим образом:
$array = $smarty->get_template_vars(); // определяем значения всех переменных:
echo 'title: '.$array['title'];
echo 'body: '.$array['body'];
Интересно, а что будет, если мы одной и той же переменной присвоим разные значения?
$smarty->assign('title', 'Title2');
У меня в этом случае заголовок страницы получился «Title2». А если я хочу присвоить одной и той же переменной два разных значения? Ну это уже тогда массив получается. Но это можно сделать в Smarty:
$smarty->append('title', 'Title2');
Теперь заголовок страницы будет «Array». Smarty понял, что это массив и сказал нам об этом английским словом. А мы этот массив должны разобрать.
Работа с массивами и циклами
Сейчас наша конкретная задача - вывести несколько заголовков (разделенных запятыми), которые запрятаны в переменной $title - в массиве:
index.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}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}<br />
{counter}
Только первый вариант гораздо компактнее.
Ах, да. Я еще забыл сказать, что в foreach, section, if и т.п., т.е. любые блоки могут содержать что угодно и быть вложенными. Главное - соблюдать очередность открытия и закрытия тегов. Например, могут быть вложенные циклы и условия: цикл-цикл, условие-условие, цикл-условие и т.д.
Каркас, на основе которого можно ставить эксперименты с Smarty, можно скачать здесь.
Резюме
Сегодня мы рассмотрели очень немногое (переменные, массивы, циклы), но достаточное, чтобы начать экспериментировать. Смарти - это как отдельный язык программирования я бы сказал даже. Поэтому рассматривать мы его будем шаг за шагом.
До следующей встречи!
Заметил такую траблу
{counter start=1 assign=test}
{counter}
{counter}
То почему то счетчик стопорится на 0 не хорошо, седня из-за этого бага долго мучился…
Странно, что он у Вас на нуле. У меня следующий код вывел цифру три:
{counter start=1 assign=test}
{counter}
{counter}
{$test}
Странно знач тот раз я чет напартачил…
Вопрос №2
{section name=catt loop=$cat} {counter assign=’test’}
{$img}{$cat[catt].name}
{if $test == ‘3’}
{assign var=”test” value=”1″}
{/if}
{/section}
Что я не так сделал или как можно по-другому?
Что мне надо переделать чтоб когда я получал 3 в test то счетчик опять шел на 1?
Спс
Для этого нужно заменить строку
{assign var=”test” value=”1″}
на
{counter assign=’test’ start=1}
Умно
Спасибо
Где продолжение? Мне понравилось. Быстро коротко и понятно. А главное работают нормально примеры..
2 anon: В нашем блоге есть и другие статьи про Smarty. Воспользуйтесь поиском.
столкнулся с оной станностью в смарти:
из файла:
$smarty->assign(‘title’,$row[0]);
$smarty->assign(‘row[1]’,$row[1]);
в html:
{$title} {*работает}
{$row[1]} {* не работает}
По видимому изза квадратных скобок в ‘row[1]’ - из-за этого не получается циклом передать данные (:
{$row.[1]} {* Кажись так надо *}
ни как не могу добиться, чтобы в выражении
$smarty->assign(‘row$i’,$row[$i]);
‘row$i’ - задался как row1 или row2; как это сделать не подскажете? Может как-то прально кавычки расставить или еще как-нить…
2 anon: странным образом вы пытаетесь вывести содержимое массива. В последнем случае нужно вот так:
$smarty->assign(“row$i”, $row[$i]);
Т.е. двойные кавычки вместо одинарных.
Но я бы на Вашем месте сделал так:
$smarty->assign(“row”, $row);
А в шаблоне обращался бы к массиву так:
{$row[0]}, {$row[1]}, …
Или для перечисления элементов массива:
{foreach from=$row item=item}
{$item}
{/foreach}
да, как-то я не подумал
Но вот с чем еще столкнулся. Нудобно на мой взгляд создавать тучу мелких вайлов .html раньше в файле .php я просто где нужно делал вставки html.. сейчас переделав под смарти, очень некрасиво получается особенно вывод таблицы. т.е. отдельно файл в котором рисуется шапка таблицы, отдельно, где она формируется и заполняется… отдельно файл (конечно не обязательно его делать, но все же ) закрывающий таблицу.. как с этим бороться? может как-то можно разграничить html так, чтоб частями вызывать… или еще как-то … подскажите?
anon, если я Вас правильно понял, Вы для каждой небольшой операции создаете отдельный шаблон и вызываете полученную коллекцию шаблонов в каком-то главном шаблоне. Вам же не обязательно делать так. Вы можете формировать шаблон так, как Вам хочется, не разбивая его на слишком мелкие части, ведь излишняя декомпозиция затрудняет чтение кода.
хм, когда читал о смарти, понял, что он сделат для того, чобы полностью отделить пхп от html. для более удобной верстки и создания и изменения дизайна… поэтому и думал если делать то так чтоб все html вставки были не в коде пхп.
В мире наблюдается тенденция отказа от смарти и тому подобных шаблонизаторов, ввиду того что php сам себе шаблонизатор, а задачу разделения логики шаблонизатор сам по себе не решает. К этому пришел и я, кстати говоря smarty более не часть проекта php
Рекомендую обратить внимание на шаблонизатор Zend_View от Zend Framework
Я думаю, что если и делать шаблонизатор, то такой где не было бы логики, чтобы были одни замены. Смысл создавать как бы еще один язык программирования? Это будет достаточно долго работать, к тому же смарти вдобавок использует классы, что несомненно отразится на производительности.
Полагаю, что Андрей скорее всего не работал над большими проектами…
народ есть вопрос …
в тэмплэйте обьявил переменные масива
{img[0]}
{img[1]}
{img[2]}
===============================
в пхп хочу отдельно занетси к примеру в элимент с индэксом 1
значение переменной $imgful… как это реализовтаь .. я уже методом потбра пыталса…в манулалах такой ситуации не описанно
$smarty->assign(‘img[1]’,”$imgful”); это не пашит
Ващет надо {$img.0}
smarty->assign(‘img’, $imgful);
Учи синтаксис самого пхп а то переменную в кавычки ставишь %)