在控制器中使用 Twig 扩展

Posted

技术标签:

【中文标题】在控制器中使用 Twig 扩展【英文标题】:Use Twig Extension in controller 【发布时间】:2012-07-10 21:04:47 【问题描述】:

我在 Twig 扩展中有一个 slugify 方法,我想在某些情况下在控制器中使用它,例如重定向。 有什么简单的方法吗? 如何从控制器中的 Twig Extensions 访问功能?

或者我是否必须将 slugify 方法作为助手才能在代码和 twig 中使用它?

【问题讨论】:

【参考方案1】:

从树枝和控制器访问功能/逻辑

我认为有两种解决方案,都应该使用Twig_Function_Method 类。

1

第一个解决方案gilden 已经发布,是将逻辑封装到服务中并为 Twig Extension 制作包装器。

2

另一种解决方案是仅使用 Twig 扩展。 Twig Extensino 已经是一项服务,您必须使用特殊的<tag name="twig.extension" /> 将其定义为服务。 但它也是一个服务,你可以通过服务容器来抓取哪个实例。并且还可以注入其他服务:

所以你有你的树枝扩展/服务:

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-&gt;container-&gt;get('acme.my_extension')

注意与普通服务的唯一区别是,twig 扩展不是延迟加载的 (http://symfony.com/doc/current/cookbook/templating/twig_extension.html#register-an-extension-as-a-service)

【讨论】:

twig 扩展已经是一项服务,这一点非常好。节省了很多时间和精力。谢谢! 记住该服务必须声明为公共的。如果有人按照食谱中的示例进行操作,则必须对其进行更改。 symfony.com/doc/current/cookbook/templating/twig_extension.html【参考方案2】:

我建议创建一个通用服务并将其注入 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...


【讨论】:

好吧,我明白了,所以我应该制作类似 StringHelper 服务的东西,并将其注入需要的地方。谢谢 我试过了,但出错了,因为Twig_Function_Method 的第一个参数必须实现Twig_ExtensionInterface @Squazic 你确实是正确的。我为此写了一个解决方法。 @gilden 你提到这并不优雅。你知道解决问题的更优雅的方法吗? @Squazic 恐怕不会。但是,您可以通过让MyTwigExtension::__call 将所有方法调用转发到服务对象来使这更加干燥。【参考方案3】:

或者另一种方法是通过 twig 获取它...(这是在 Symfony 2.7 上)

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

因此,如果您的 Twig 扩展类名为“MyFabulousTwigExt”,那么您将调用

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

当上述方法不起作用时,这对我有用(我们的扩展程序也不是服务)

【讨论】:

以上是关于在控制器中使用 Twig 扩展的主要内容,如果未能解决你的问题,请参考以下文章

从扩展中获取当前控制器动作和 slug

Twig 模板布局 Yii2 框架

在 Twig 模板中使用 Symfony2 控制器返回

在 TWIG 模板中获取控制器名称

限制字符串树枝

从内部控制器和twig访问rest API