Все что нужно знать про twig. PHP шаблонизатор Twig

Как правило, все шаблонизаторы похожи друг на друга и различаются только какими-то специфическими особенностями и деталями. Главная задача шаблонизаторов - разделить бизнес логику приложения и вывод данных на страницу, таким образом, позволив разработчикам и дизайнерам работать одновременно, не капая друг другу на мозги.

Многие PHP фрэймворки, включая: Zend Frameworkd, Agavi, CackPHP и CodeIgniter, по-своему реализуют разделение бизнес логики и вывод данных. Однако, если вы не любите фрэймворки или ваш проект слишком мал для их использования, то вы можете воспользоваться какой-то отдельной системой построения шаблонов. К счастью, нам есть из чего выбирать. Smartym Savant, Dwoo... этот список можно продолжать и продолжать, однако в этой статье я покажу вам, как работать с шаблонизатором Twig.

Установка

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

Основы

Прежде чем приступить непосредственно к делу, давайте разберёмся с принципом работы шаблонизаторов. Обычное PHP приложение состоит из целого набора страниц, которые включают в себя как статический HTML код (меню, списки, изображения и т.д.), так и динамический контент (вывод данных из БД, xml файла, сервисы, …). С помощью Twig мы можем разделить данные процессы, создавая шаблоны со специальными маркерами, вместо которых в последствии будет вставляться динамический контент.

Значения для данных маркеров формируются в основном PHP скрипте; там же происходит общение с базой данных, xml парсинг и другие всевозможные операции. Таким образом, ваша страница будет строиться на основе 2х источников: шаблона с специальными вставками и PHP скриптов, где мы храним основной функционал. Это даёт возможность PHP разработчикам и дизайнерам одновременно работать над одними и теми же страницами.

Приступаем к делу

Для того чтобы посмотреть, как работает Twig, предлагаю рассмотреть простой пример:

Account successfully created!

Hello {{ name }}

Thank you for registering with us. Your account details are as follows:

Username: {{ username }}
Password: {{ password }}

You"ve already been logged in, so go on in and have some fun!

Сохраните данный файл templates/thanks.tmpl. Обратите внимание на то, что все маркеры, представляющие собой переменные, помещены в двойные фигурные скобки. Подобная запись подскажет Twig-у, где и как осуществлять вставку данных.

Затем, нам необходимо создать основной скрипт, где будет происходить формирование переменных и данных:

В результате, если вы откроете данную страницу в браузере, то увидите следующее:

Для использования Twig-а, вам нужно пройти следующие шаги:

  • Инициализировать авто-загрузчик Twig-а, для того чтобы классы шаблонизатора подгружались автоматически.
  • Инициализировать загрузчик шаблонов. В нашем случае эт Twig_Loader_FileSystem. В качестве аргумента передаём путь к каталогу с шаблонами.
  • Создать объект самого Twig и передать ему уже сконфигурированные настройки.
  • Подгрузить нужный нам шаблон с помощью метода loadTemplate, передав в него название используемого шаблона. В качестве результата метод вернёт экземпляр шаблона.
  • Сформировать массив вида "ключ-значение", где ключи - это названия переменных, а значения - данные, выводимые в шаблоне. Затем этот массив нужно передать в метод render(), который совместит шаблон с переданными данными и вернёт сгенерированный результат.
  • Условия

    Twig также предоставляет нам возможность создавать условные выражения ‘if-else-endif’. Пример:

    Odd or Even {% if div == 0 %} {{ num }} is even. {% else %} {{ num }} is odd. {% endif %}

    В зависимости от числа, которое генерируется в основном PHP скрипте, шаблон отобразит одно из двух сообщений. Вот и скрипт, где генерируется число от 0 до 30 и проверяется на чётность:

    а вот и результат:

    Также мы можем сделать многоуровневые проверки ‘if-elseif-else-endif’. Пример:

    Seasons {% if month > 0 and month 3 and month 6 and month 9 and month

    А вот и вывод:

    Циклы

    Twig также поддерживает цикл ‘for’. Он очень удобен, если нам необходимо пройтись по массиву. Пример:

    Shopping list

      {% for item in items %}
    • {{ item }}
    • {% endfor %}

    В данном примере у нас простой не ассоциативный массив. На каждой итерации мы будем получать по одному элементу и выводить его в элементе списка. Вот и скрипт:

    Результат:

    Для того чтобы пройтись по ассоциативному массиву, мы можем обращаться к ключам через “точку”. Пример:

    Для того чтобы достучаться до значений массива в шаблоне, сначала пишем имя переменной, в которой хранится сам массив. Затем ставим точку и пишем название ключа, по которому достаём данные:

    Book details

    Title {{ book.title }}
    Author {{ book.author }}
    Publisher {{ book.publisher }}
    Pages {{ book.pages }}
    Category {{ book.category }}

    Результат:

    Такой же подход может быть применён для работы с объектами.

    Дамп данных

    Безусловно циклы вам пригодиться при выводе данных из БД. Пример:

    table { border-collapse: collapse; } tr.heading { font-weight: bolder; } td { border: 1px solid black; padding: 0 0.5em; } Countries and capitals

    {% for d in data %} {% endfor %}
    Country Region Population Capital Language
    {{ d.name|escape }} {{ d.region|escape }} {{ d.population|escape }} {{ d.capital|escape }} {{ d.language|escape }}

    В следующем фрагменте кода я использую PDO подключение к MySQL базе данных ‘world’. Если вы хотите попробовать данный пример, то вам нужно сформировать базу самим:

    Тут стоит отметить несколько вещей:

    Мы используем метод getchObject(), который вернёт нам строки из таблицы в виде объектов. Названия полей будут соответствовать названиям колонок. Затем эти объекты мы помещаем в массив и передаём его в шаблон. В шаблоне, используем цикл и выводим данные.

    В данном примере также используется встроенный в Twig фильтр `escape`. По умолчанию данный фильтр пользуется функцией htmlspecialchars() для фильтровки данных. Это неплохая защита от XSS атак.

    Подгрузка шаблонов

    Также в Twig-е есть ещё одна команда - `include`, которая позволяет подключать содержание других шаблонов. Это может пригодиться, когда вы захотите прикрепить к вашим файлам меню, заголовок или подвал.

    Для демонстрации представьте, что данный код - это главный шаблон:

    {% include "primary.tmpl" %} {% include "secondary.tmpl" %} This is the main page content. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. {% include "footer.tmpl" %}

    Все секции данной страницы находятся в отдельных файлах и подключаются сюда с помощью команды `include`. Давайте посмотрим, как выглядят подключаемые файлы:

    {% for item in nav.primary %} {% endfor %}
    {{ item.name|upper }}

      {% for item in nav.secondary %}
    • {{ item.name }}
    • {% endfor %}

    This page licensed under a Creative Commons License. Last updated on: {{ updated }}.

    А вот и главный PHP скрипт:

    Обратите внимание, что нам не нужно загружать все шаблоны функцией loadTemplate. Главное подключить основной шаблон. Каждый мелкий под-шаблон загрузится автоматом. Переменные и значения, переданные в главный шаблон, будут доступны во всех подключаемых шаблонах.

    Результат:

    Фильтрация данных

    В данной статье мы уже затронули тему фильтров. Давайте посмотрим, какие ещё возможности в данной сфере предоставляет нам Twig.

    Давайте рассмотрим, к примеру, фильтр ‘date’. Данный фильтр даёт нам возможность формировать дату и время, используя нативные для PHP маркеры. Пример:

    {{ "now"|date("d M Y h:i") }}
    {{ "now"|date("d/m/y") }}

    Результат:

    Также вы можете воспользоваться фильтрами `upper`, `lower`, `capitalize`, `title` для контроля заглавных и прописных букв:

    {{ "the cow jumped over the moon"|upper }}
    {{ "the cow jumped over the moon"|capitalize }}
    {{ "the cow jumped over the moon"|title }}
    {{ "The Cow jumped over the Moon"|lower }}

    Результат:

    Фильтр `striptags` уберёт из текста все HTML и XML элементы:

    {{ "I said \"Go away!\""|striptags }}

    Результат:

    Фильтр `replace` позволяет быстро и просто заменять какие-то значения в строке на нужные нам. Пример:

    {{ "I want a red boat"|replace({"red" : "yellow", "boat" : "sports car"}) }}

    Результат:

    Вы уже видели фильтр `escape` в действии. В Twig также есть фильтр, который делает абсолютно противоположное действие - `raw`. Его следует использовать только для html кода, который вы считаете 100% безопасным.

    Escaped output: {{ html|escape }}
    Raw output: {{ html|raw }}

    Если же вам нужно применить `escape` к большому блоку кода, то вы можете воспользоваться синтаксисом `autoescape`, передав булево значение true/false для активации и дезактивации фильтрации `escape`. Пример:

    {% autoescape true %} Escaped output: {{ html }}
    {% endautoescape %} {% autoescape false %} Raw output: {{ html }} {% endautoescape %}

    Теперь вы уже больше знаете о Twig-e и можете использовать условия, циклы и фильтры.

    Twig 2 - Twig for Template Designers

    Twig для дизайнеров шаблонов

    Этот документ описывает синтаксис и семантику механизма шаблона и будет наиболее полезен в качестве ссылки на те, которые создают шаблоны Twig.

    конспект

    Шаблон - это просто текстовый файл. Он может генерировать любой текстовый формат (HTML, XML, CSV, LaTeX и т. Д.). У него нет определенного расширения, .html или.xml просто отлично.

    Шаблон содержит переменные или выражения , которые заменяются значениями при оценке шаблона и тегами , которые управляют логикой шаблона.

    Ниже приведен минимальный шаблон, который иллюстрирует несколько основ. Ниже мы расскажем о следующих деталях:

    My Webpage

    My Webpage {{ a_variable }}

    Существует два типа разделителей: {% ... %} и {{ ... }} . Первый используется для выполнения таких операторов, как for-loops, последний печатает результат выражения в шаблоне.

    Интеграция с IDE

    Многие IDE поддерживают подсветку синтаксиса и автозаполнение для Twig:

    • Textmate через пакет Twig
    • Vim через плагин синтаксиса Jinja или плагин vim-twig
    • Netbeans через плагин синтаксиса Twig (до 7.1, родной по 7.2)
    • PhpStorm (родной от 2.1)
    • Eclipse через плагин Twig
    • Возвышенный текст через пакет Twig
    • GtkSourceView через определение языка Twig (используется gedit и другими проектами)
    • Coda и SubEthaEdit через синтаксический режим Twig
    • Coda 2 через другой синтаксический режим Twig
    • Комодо и Комодо Редактировать через режим Twid подсветки / синтаксиса
    • Блокнот ++ через Notepad ++ Twig Highlighter
    • Emacs через web-mode.el
    • Atom через PHP-ветку для атома
    • Код Visual Studio через пакет Twig

    Реализация

    Для удобства foo.bar выполняет следующие действия на уровне PHP:

    • если нет, и если foo является объектом, проверьте, что bar является допустимым свойством;
    • если нет, и если foo является объектом, проверьте, что bar является допустимым методом (даже если bar является конструктором - вместо этого используйте __construct());
    • если нет, и если foo является объектом, проверьте, что getBar является допустимым методом;
    • если нет, и если foo является объектом, проверьте, что isBar является допустимым методом;
    • если нет, и если foo является объектом, проверьте, что hasBar является допустимым методом;

    foo["bar"] с другой стороны, работает только с массивами PHP:

    • проверьте, является ли foo массивом и bar действительный элемент;
    • если нет, верните null значение.
    Глобальные переменные

    В шаблонах всегда доступны следующие переменные:

    • _self: ссылается на текущее имя шаблона;
    • _context: ссылается на текущий контекст;
    • _charset: ссылается на текущую кодировку.
    Установка переменных

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

    {% set foo = "foo" %} {% set foo = %} {% set foo = {"foo": "bar"} %}

    фильтры

    Переменные могут быть изменены фильтрами . Фильтры отделяются от переменной символом (|) и могут иметь необязательные аргументы в круглых скобках. Несколько фильтров могут быть скованы цепью. Выход одного фильтра применяется к следующему.

    В следующем примере удаляются все теги HTML из name и заголовков:

    {{ name|striptags|title }}

    Фильтры, которые принимают аргументы, имеют круглые скобки вокруг аргументов. Этот пример присоединяется к списку через запятую:

    {{ list|join(", ") }}

    Чтобы применить фильтр к разделу кода, оберните его в тег filter :

    {% filter upper %} This text becomes uppercase {% endfilter %} Members

      {% for user in users %}
    • {{ user.username|e }}
    • {% endfor %}
    {{ user.username|e }}

    По умолчанию фильтр-победитель использует html стратегию, но в зависимости от контекста экранирования вы можете явно использовать любые другие доступные стратегии:

    {{ user.username|e("js") }} {{ user.username|e("css") }} {{ user.username|e("url") }} {{ user.username|e("html_attr") }}

    Работа с автоматическим экранированием

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

    {% autoescape %} Everything will be automatically escaped in this block (using the HTML strategy) {% endautoescape %}

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

    {% autoescape "js" %} Everything will be automatically escaped in this block (using the JS strategy) {% endautoescape %}

    Спасаясь

    Иногда желательно или даже необходимо, чтобы Twig игнорировали части, которые иначе обрабатывались бы как переменные или блоки. Например, если используется синтаксис по умолчанию, и вы хотите использовать {{ качестве исходной строки в шаблоне и не запускать переменную, вам нужно использовать трюк.

    Самый простой способ - вывести разделитель переменных ({{), используя переменное выражение:

    {{ "{{" }}

    Для больших разделов имеет смысл отметить блок verbatim .

    макрос

    Макросы сопоставимы с функциями на обычных языках программирования. Они полезны для повторного использования часто используемых фрагментов HTML, чтобы не повторять себя.

    {% if phone matches "/^[\\d\\.]+$/" %} {% endif %}

    Оператор сдерживания

    Оператор in выполняет тест на герметичность.

    Он возвращает true если левый операнд содержится справа:

    {# returns true #} {{ 1 in }} {{ "cd" in "abcde" }}

    Наконечник

    Вы можете использовать этот фильтр для выполнения теста сдерживания на строках, массивах или объектах, реализующих интерфейс Traversable .

    Чтобы выполнить отрицательный тест, используйте оператор not in операторе:

    {% if 1 not in %} {# is equivalent to #} {% if not (1 in ) %}

    Оператор тестирования

    Оператор выполняет тесты. Тесты могут быть использованы для проверки переменной на общее выражение. Правильный операнд - это имя теста:

    {# find out if a variable is odd #} {{ name is odd }}

    Тесты также могут принимать аргументы:

    {% if post.status is constant("Post::PUBLISHED") %}

    Тесты могут быть сведены на нет с помощью оператора is not:

    {% if post.status is not constant("Post::PUBLISHED") %} {# is equivalent to #} {% if not (post.status is constant("Post::PUBLISHED")) %}

    Добавляем шаблонизатор Twig как плагин для WordPress.
    Возможно, многие из вас сейчас крутят у веска пальцем и задаются вопросом – «Зачем это нужно?», и возможно вполне правы, наверняка это весьма сумасшедшая идея, но я все же скажу – «а почему бы и нет?».

    Для начала познакомимся с Twig. Что это такое? – Twig это PHP шаблонизатор нового поколения, написанный Fabien Potencier, создателем фреймворка Symfony, в последней версии которого он как раз используется.

    Как говорится на официальном сайте, данного чуда:

    Быстрый – Twig компилирует шаблоны и при желании складывает их в Кеш, при этом скомпилированный PHP код полностью соответствует ООП, оптимизирован и скорость его последующей работы равна скорости работы обычного PHP кода.

    Безопасный – Twig имеет изоляционный режим (режим песочницы), для работы с ненадежным кодом шаблона. Пользователь, имеющий доступ к шаблону, и возможность его редактировать не сможет воспроизвести произвольный код, или получить доступ к данным не касающихся непосредственно его, и нанести ущерб системе в целом.

    Гибкий – Twig оснащен гибким лексическим и синтаксическим анализатором кода, это позволяет разработчику определять собственные пользовательские теги и фильтры.

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

    Думаю предельно понятно почему я решил использовать именно твиг в качестве шаблонизатора для CMS WordPress, кроме всего это будет способствовать организации кода в шаблоне. Но главной причиной можно считать любопытство и интерес к данной задумке, удовлетворение не преодолимого желания привинтить твиг к своему блогу.

    Я не очень люблю смешивать HTML и PHP теги, по этому в самописных проектах я предпочитаю использовать паттерн MVC, но в данном случаи такой возможности нет. Поэтому, после долгих размышлений, о том как реализовать мою идею, было принято решение написать плагин, который будет обеспечивать все необходимые задачи и позволит использовать twig.

    Сначала я создал папку с именем плагина wp_twig_engine, затем в неё копируем папку Lib шаблозатора, скачать шаблонизатор с офф. сайта , таким образом, мы превратили весь набор скриптов твига в плагин для WP.

    Затем создаем главный файл плагина: WP-twig.php, с содержимым

    Просмотр кода PHP

    Просмотр кода PHP