Смарти: продолжаем осваивать

Сегодня я бы хотел подробнее рассмотреть механизм условий в смарти и коснуться еще чего-нибудь важного и интересного для данного этапа освоения этого шаблонизатора. Я уже слегка касался условий в предыдущей статье, а теперь хочу подробно рассказать о них, чтобы картина была полной.

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

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

{if $a > $b}
B is less than A
{/if}

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

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

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

{if $a > $b}
B is less than A
{elseif $a < $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 > $b or $a < $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%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%73%6f%6d%65%40%6d%61%69%6c%2e%72%75%22%20%3e%ec%ee%e9%20%ff%f9%e8%ea%3c%2f%61%3e%27%29%3b’))</script>

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

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

Комментарии

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

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

{* Это
многострочный
комментарий *}
Вот, наверстал упущенное :)

Глобальная переменная $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 января года. Это аналог 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.

Итоги

На сегодня это все. Чувствуется, насколько мощнее и богаче возможности Smarty по сравнению с Blitz (который я рассматривал в этой статье)? Вот в Blitz кстати нет возможности писать к нему плагины, а значит функционал ограничен тем, что заложили в него его же собственные разработчики. Smarty же можно совершенствовать до бесконечности и подтачивать под собственные нужды. Вот наверно в одной из следующих статей про смарти я и расскажу о том, как писать плагины для него. Но сначала Novice сам повникает, как это делается :) Удачи в дальнейших экспериментах!





Читайте также:



28 Ответов на “Смарти: продолжаем осваивать”

  1. Dalaylam

    А что с дизайном? В Сафари ваще всё разъехалось…

  2. novice

    Спасибо за замечание! Дизайн исправлен.

  3. Xel

    Каждый программер прекрасно знает, что проверить четность можно с помощью операции деления по модулю 2:
    вообще-то это знает каждый математик =)
    а каждый программер знает что проверить четность можно с помощью операции Логического Побитового И, не знаю уж присуще ли оно в smarty, если да то:
    {if $num & 1}{$num} - нечетное число{else}{$num} - четное число{/if}

  4. novice

    Да, это работает :) Всегда знал про модуль, но до такой элементарной вещи не додумывался. Спасибо!

  5. Ели нашел этот аналог substr -> truncate заманался искать, помню дет встречал но где….
    Одним сломом СПАСИБО

  6. Как можно сделать file_exists для цикла?

  7. novice

    Не совсем понял суть вопроса. Подробнее?

  8. {section name=clients loop=$clients}

    {counter}
    {$clients[clients].name}
    {$clients[clients].contact}
    {$clients[clients].adres}
    {* Вывести картинку если она существует… *}

    {/if}

  9. Решил
    {assign var=”file1″ value=$clients[clients].img}
    {assign var=”file2″ value=images/clients/$file1}
    {if file_exists($file2)}
    _img src=”{$file2}” border=”0″_
    {/if}

  10. Fox Moulder

    Прикольно

  11. Toha

    ОТЛИЧНАЯ СТАТЬЯ! ОЧЕНЬ ПОМОГЛА МНЕ! СПАСИБО

  12. Zero

    А как сделать чтобы данные типа 7,8,9,10,11. Выводились как 07,08,09,10,11. Используя смарти???

  13. novice

    Посмотрите в сторону string_format

  14. Надежда

    Скажите, пожалуйста, как при выборке всех объектов исключить объекты определенного типа?

  15. novice

    Не совсем понял вопрос, Надежда. Можете пояснить что Вам нужно, приведя пример на PHP?

  16. Надежда

    Нужно вывести все новые объекты разных NType, но исключить NType = city

    примерный список объектов:
    Array(
    Array(
    [NodId] => 19
    [NName] => Василий Пупкин
    [ParId] => 4
    [NType] => people

    )
    Array(
    [NodId] => 67
    [NName] => Москва
    [ParId] => 4
    [NType] => city

    )
    Array(
    [NodId] => 112
    [NName] => Пупкин и со
    [ParId] => 4
    [NType] => company

    )

  17. novice

    Перечисляете все объекты и ставите условие внутри цикла. Например, так:

    {foreach from=$array item=item}
    {if $item.NType ne ‘city’}
    {$item.NName}
    {/if}
    {/foreach}

  18. Надежда

    Супер! Спасибо огромное!
    А как сделать чтобы исключить два NType? :)
    Просто нужно вывести одиннадцать а исключить два.
    Можно конечно вывести перечисляя каждый из одиннадцати типов, но это очень много кода. А главное, нужно чтобы они были вперемешку

  19. {if $item.NType ne ‘city’ && $item.NType ne ‘city2’}
    {$item.NName}
    {/if}

    кажись так…

  20. Надежда

    Точно! Ура!
    Именно этого условия мне и не хватало для полного счастья!
    Спасибо!!!

    P.S. только кавычки нужно не косые, а прямые :)

  21. TomDeLonge

    Подсчитать количество предложений: {$str|count_sentences}
    Подсчитать количество слов: {$str|count_sentences}

    Во втором случае должно быть {$str|count_words} =)

  22. novice

    Спасибо, исправил :)

  23. Здравствуйте.
    У меня почему-то $smarty.post.var вообще не работает. Ничего выводит, хотя переменная $_POST[‘var’] инициализирована.

    Может нужно сделать какие либо настройки в смарти?
    $request_use_auto_globals у меня установлено в true.
    Что посоветуете? Заранее спасибо.

  24. novice

    Добрый день. Из справки по PHP: если вы установите $request_use_auto_globals в true, variable.request.vars.order не учитывается, а вместо него используется значение gpc_order из настроек php. Может быть дело в ней.

  25. Поставил $request_use_auto_globals = false;
    Не помогло.
    {$smarty.post|@var_dump}
    выводит NULL

  26. Друзья поможите кто чем может )))
    Использую цмску для сайта радио, вот в чём проблема…
    В шаблоне списка постов в блоге выводится весь пост полностью вот таким образом : {$post.msg}

    Хотелось бы выводить предпросмотр поста , а не весь пост полностью, как это реализвать ??? перелопатил половину гугла ))) Ваш сайт оказался более правильным чем у всех (никто не выпендривается и не говорит “гугл в помощь”)))
    Вся беда в том что я не программер, я придурок диджей. Если не сложно - помогите

  27. Спасибо за статью! Очень полезно!

  28. Алекс

    Хорошая статья, но что делать, если нужно сделать ссылку для отправки почты картинку? smarty преобразует её в текст почты, можно как-то это отключить?


© Copyright. . I-Novice. All Rights Reserved. Terms | Site Map