Используйте расширение Twig в контроллере

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

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


person ivoba    schedule 11.07.2012    source источник


Ответы (3)


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

namespace Acme\Bundle\DemoBundle\...;

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

    // additional methods...
}

EDIT - как упоминал Squazic, первый аргумент должен реализовывать 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...

}
person kgilden    schedule 11.07.2012
comment
Хорошо, я понимаю, поэтому я должен сделать что-то вроде службы StringHelper и внедрить ее туда, где она нужна. Спасибо - person ivoba; 11.07.2012
comment
Я попробовал это, но получил ошибку, потому что первый аргумент Twig_Function_Method должен реализовать Twig_ExtensionInterface - person Squazic; 28.09.2012
comment
@Squazic Вы действительно правы. Я написал обходной путь для этого. - person kgilden; 28.09.2012
comment
@gilden Вы упомянули, что это не элегантно. Знаете ли вы более элегантный способ решения проблемы? - person Squazic; 28.09.2012
comment
@Squazic Боюсь, что нет. Однако вы можете сделать это немного более СУХИМ, добавив MyTwigExtension::__call перенаправлять все вызовы методов объекту службы. - person kgilden; 01.10.2012

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

Я думаю, что для этого есть два решения, оба должны использовать класс 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')

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

person timaschew    schedule 12.04.2013
comment
Очень хороший момент в том, что расширение twig уже является сервисом. Сэкономил много времени и сил. Спасибо! - person Wiseman; 19.07.2016
comment
Помните, что сервис должен быть объявлен как общедоступный. Если кто-то следует примеру из поваренной книги, то должен это изменить. symfony.com/doc/current/cookbook/templating/twig_extension.html - person glerendegui; 27.07.2016

Или другой способ получить его через ветку... (это на Symfony 2.7)

$twigExt = $this->container->get('twig')->getExtension(TwigExtensionClassName::class);

Итак, если ваш класс расширения Twig называется «MyFabulousTwigExt», вы должны позвонить

$twigExt = $this->container->get('twig')->getExtension(MyFabulousTwigExt::class);

Это сработало для меня, когда вышеперечисленное не сработало (наше расширение также не было сервисом)

person Steve Childs    schedule 01.09.2018