Использовать Twig Extension в контроллере

У меня есть метод slugify в расширении Twig, который я хотел бы использовать в некоторых случаях в контроллере, т.е. с перенаправлением.
Есть ли простой способ для этого?
Как я могу получить доступ к функциям из Twig Extensions в контроллере?

Или мне нужно сделать метод slugify некогда помощником, чтобы использовать его в коде и в twig?

Ответ 1

Я бы посоветовал создать общий сервис и ввести его в расширение Twig. Расширение будет действовать как оболочка для службы.

namespace Acme\Bundle\DemoBundle\...;

class MyService
{
    public function myFunc($foo, $bar)
    {
        // some code...
    }

    // additional methods...
}

EDIT - как упоминалось Squasic, первый аргумент должен реализовать Twig_ExtensionInterface. Неэлегантным решением было бы добавить методы к MyTwigExtension, которые в свою очередь вызывают соответствующие методы в службе.

namespace Acme\Bundle\DemoBundle\Twig\Extension;

class MyTwigExtension extends \Twig_Extension
{
    protected $service;

    public function __construct(MyService $service)
    {
        $this->service = $service;
    }

    public function getFunctions()
    {
        return array(
            'myTwigFunction' => new \Twig_Function_Method($this, 'myFunc'),
            'mySecondFunc'   => new \Twig_Function_Method($this, 'mySecondFunc'),
        );
    }

    public function myFunc($foo, $bar)
    {
        return $this->service->myFunc($foo, $bar);
    }

    // etc...

}

Ответ 2

Функция доступа/логика от веточки и контроллера

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

1

Первое уже принятое решение gilden - это инкапсулировать логику в службу и сделать оболочку для расширения Twig.

2

Другим решением является использование только расширения Twig. Twig Extensino уже является сервисом, вы должны определить его как услугу со специальным <tag name="twig.extension" />. Но это также сервис, который вы можете захватить контейнером сервиса. А также можно вводить другие услуги:

Итак, у вас есть расширение/сервис Twig:

class MyTwigExtension extends \Twig_Extension
{
    private $anotherService;

    public function __construct(SecurityService $anotherService= null)
    {
        $this->anotherService = $anotherService;
    }

    public function foo($param)
    {
       // do something
       $this->anotherService->bar($param);
    }


    public function getFunctions()
    {
        // function names in twig => function name in this calss
        return array(
            'foo' => new \Twig_Function_Method($this, 'foo'),
        );
    }

    /**
     * Returns the name of the extension.
     *
     * @return string The extension name
     */
    public function getName()
    {
        return 'my_extension';
    }
}

Образ services.xml выглядит следующим образом

<service id="acme.my_extension" class="Acme\CoreBundle\Twig\Extension\MyTwigExtension">
        <tag name="twig.extension" />
        <argument type="service" id="another.service"></argument>
</service>

Чтобы перейти к сервису с вашего контроллера, вам нужно использовать это:
 $this->container->get('acme.my_extension')

Примечание Единственное отличие от обычной службы заключается в том, что расширение ветки не загружается без лжи (http://symfony.com/doc/current/cookbook/templating/twig_extension.html#register-an-extension-as-a-service)