Использование строки в качестве Twig шаблона в Symfony2

Я переключил свой предпочтительный метод на использование класса Twig_Loader_Chain. Этот метод позволяет назначить несколько загрузчиков в один экземпляр Twig_Environment, так что вы сможете прозрачно обрабатывать шаблоны из файлов или из строк. В нижней части статьи вы увидите описание этого метода.

Для того, чтобы создать twig шаблон требуется экземпляр класса Twig_Environment. Этот класс содержит метод render, который возвращает обработанный результат из twig шаблона (обычно из файла). Twig Environment использует загрузчик классов, который реализует интерфейс Twig_LoaderInterface, этот класс загружает данные из хранилища (файл, база данных) для последующего их анализа шаблонизатором. По умолчанию Symfony2 использует класс Twig_Loader_Filesystem, который загружает данные шаблонов из файлов, для того чтобы создать шаблон из строки нам нужен экземпляр Twig_Environment, который для получения данных, использует класс Twig_Loader_String. Есть несколько способов, как вы можете это сделать, самый простой способ — это создать экземпляр Twig_Environment и и в качестве загрузчика передать ему экземпляр класса Twig_Loader_String (этот код можно поместить внутри вашего контроллера):

<?php
$twig = new \Twig_Environment(new \Twig_Loader_String());
$rendered = $twig->render(
    "Test string template: {{ result }}",
    array("result" => "Success!")
);

Это прекрасно работает как быстрое решение, но проблема здесь заключается в том, что в шаблоне вы не будете иметь доступ к Symfony сервисам или пользовательским сервисам, это потому, что мы создали свежий экземпляр Twig_Environment без каких-либо дополнительных настроек, которые предоставляет Symfony. Лучше взять копию существующего сервиса Twig_Environment, используемого самим Symfony и изменить его для использования Twig_Loader_String (вы можете использовать это в вашем контроллере):

<?php
$twig = clone $this->get('twig');
$twig->setLoader(new \Twig_Loader_String());
$rendered = $twig->render(
    "Test string template: {{ result|humanize }}",
    array("result" => "mega_success")
);

Здесь я клонировал оригинальный сервис Symfony, чтобы убедиться, что Symfony по-прежнему может обработать шаблон из файла. Другой метод заключается в том, чтобы создать свой собственный Twigсервис с помощью системы внедрения зависимостей Symfony. Здесь я добавил пользовательский Twig сервис в мой config.yml проекта:

services:
    mine.twig_string_loader:
        class: "Twig_Loader_String"
    mine.twig_string:
        class: "%twig.class%"
        arguments: [@mine.twig_string_loader, %twig.options% ]

Затем можно использовать этот сервис в пределах вашего контроллера, вот так:

<?php
$rendered = $this->get('mine.twig_string')->render(
    "Test string template: {{ result }}",
    array("result" => "Success!")
);

К сожалению, этот метод имеет те же ловушки как и в первом методе, он не будет включать любые Symfony Twig расширения или собственные расширения. Конечно эти расширения можно добавить в этот пользовательский Twig сервис, но гораздо легче просто клонировать существующий Twig сервис и изменить, при необходимости. Как упоминалось выше использование Twig Chain Loader , является предпочтительным методом, используйте его, чтобы назначить несколько загрузчиков Symfony в основной Twig экземпляр. Для использования этого метода необходимо использовать Symfony2.2 или выше. Добавление дополнительного загрузчика к экземпляру Symfony Twig может быть достигнуто путем создания нового Twig_Loader_String загрузчика, следующим образом:

twig.stringloader:
    class: Twig_Loader_String
    tags:
        - { name: twig.loader }

Эти настройки должны быть добавлены в файл config.yml или конфигурационный файл вашего бандла. Важной частью здесь является тег twig.loader — это говорит Symfony, что нужно назначить класс Twig_Loader_String, как дополнительный загрузчик в основной Twig экземпляр. Красота этого метода заключается в том, что Symfony будет отображать шаблоны из файлов и строковые шаблоны прозрачно без каких-либо дополнительных усилий. Вы можете просто вызвать метод render и передать в него строку или ссылку на файл шаблона, и Twig сам определит, какой загрузчик использовать для вашего шаблона. Ниже приведен пример этого в действии:

<?php
class DefaultController extends Controller
{
    public function indexAction()
    {
        $renderedString = $this->get('twig')->render('{{ name }}', array('name' => 'test'));
        $renderedTemplate = $this->get('twig')->render('MyBundle:Default:index.html.twig');
    }
}

Оба вызова будут успешно обрабатывать шаблоны. Twig сервис определит, какой загрузчик нужно использовать на основе предоставленных данных.