【问题标题】:Symfony2 call controller-action in twig-extension without serviceSymfony2 在没有服务的情况下在树枝扩展中调用控制器动作
【发布时间】:2016-01-30 17:14:18
【问题描述】:

我正在编写一个具有以下功能的系统:普通用户(没有程序员或管理员)可以创建可以插入“占位符”的内容。呈现页面时,这些占位符将替换为不同的内容类型(例如,十六进制颜色代码、滑块、图像……)。占位符的替换有点复杂,并且有一些额外的功能(例如,定义默认值,用正确语言的内容替换占位符,...)。因此,我创建了一个带有“占位符过滤器”的树枝扩展。此函数应获取正确的内容以替换占位符并处理附加功能。

因为内容类型是如此不同,所以对于每个包含在控制器中呈现内容的逻辑的内容类型,都有一些 - 让它称之为“插件”。

现在我的问题:

插件的控制器动作返回渲染的内容。因为我用树枝扩展中的内容替换占位符,所以我需要一种方法来调用此树枝扩展中的控制器操作。

到目前为止我的想法:

我知道我可以通过这种方式在模板中调用控制器动作(来源:http://symfony.com/doc/current/book/templating.html):

{{ render(controller(
        'AppBundle:Article:recentArticles',
        { 'max': 3 }
    )) }}

所以在 twig 中调用控制器动作似乎没有问题。但我需要在 twig-extension 中调用这个函数。

我还知道,当我将控制器实现为服务时,我可以调用控制器动作。但我不能将所有插件控制器都定义为服务,因为插件是动态包含在系统中的。在安装新插件时动态处理服务也将是“困难的”(我认为我必须使用脚本编辑 service.yml - 或者我错了吗?)。这就是为什么我不能将控制器用作服务。 - 但是当您告诉我如何动态实现服务时,我愿意接受其他解决方案。

我已经尝试过结合这两个页面的解决方案: http://symfony.com/doc/current/book/templating.html

echo $view['actions']->render(
    new \Symfony\Component\HttpKernel\Controller\ControllerReference(
        'AppBundle:Article:recentArticles',
        array('max' => 3)
    )
)

https://www.robinvdvleuten.nl/blog/rendering-templates-in-a-twig-extension/

我现在可以在我的 twig-extension 的占位符过滤器中访问 Twig_Environment,但以下代码不起作用:

$twig->render( new \Symfony\Component\HttpKernel\Controller\ControllerReference(
                            'Extensions'.$namespace.'Bundle:Index:getContent',
                            array('content'=>$contentObject)
                        ), array() );

我收到 ControllerReference 无法转换为字符串的错误(这是有道理的,因为 ControllerReference 是一个对象......)。

那么有没有办法在 twig-extension 中调用控制器操作而不将控制器定义为服务?还是我应该重新考虑整个解决方案?

【问题讨论】:

  • 绝对重新考虑解决方案。 IMO,您应该制作侦听器或简单的服务来解析文本并返回预期的输出。此外,您应该制作某种缓存来存储该输出,而不是在每次请求时解析它。

标签: symfony twig-extension


【解决方案1】:

也许您可以定义一个 ViewListener 并让您的控制器返回您想要的 html,而不是控制器上的 $this->render 返回的响应。

您需要在控制器上使用 $this->renderView 并将结果返回给您的扩展。

老实说,我觉得像这样设置的整个系统会很老套,很难长期维护,所以我建议重新考虑一下

【讨论】:

    【解决方案2】:

    在“思考问题”几个小​​时后,我找到了主要问题的简单答案。当我在我的过滤器函数中包含 Twig_environment(请参阅https://www.robinvdvleuten.nl/blog/rendering-templates-in-a-twig-extension/)时,我可以访问 twig 渲染()函数。该函数适用于模板和字符串。因此,在没有服务的情况下在 twig-extension 中调用控制器操作的最简单方法是使用普通的 twig-template-syntax:

    // $twig is the Twig_Environment in my filter-function
    $myRenderedContent = $twig->render(
        "{{ render(controller( 'Extensions".$namespace."Bundle:Index:getContent', { 'content': content })) }}", 
        array('content'=>$contentObject)
    );
    

    其他想法:

    正如您在http://symfony.com/doc/current/book/templating.html 中看到的那样,在 symfony 中调用这样的控制器似乎完全没问题。所以我认为在 twig-extension 中使用这个功能也是可以的(因为 twig-extension 为模板渲染定义了额外的辅助函数,这就是我想要用我的过滤器函数来用特殊的占位符替换特殊的占位符内容)。

    也许不将我的插件控制器作为服务包括在内不是最佳做法,但到​​目前为止我还没有看到像这样处理插件控制器的缺点 - 当你知道一个时:请告诉我,因为我我愿意学习“如何让它变得更好”;-)

    【讨论】:

    • 注意:此解决方案并非在所有情况下都有效。有时您必须使用 Twig_Loader_Array 来呈现“模板字符串”。有关呈现字符串和缓存的更多信息,另请参阅stackoverflow.com/questions/31081910/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 2021-11-10
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多