symfony2在没有服务的twig-extension中调用controller-action

时间:2016-01-30 17:14:19

标签: symfony twig-extension

我正在编程具有以下功能的系统:普通用户(没有程序员或管理员)可以创建可以插入"占位符"的内容。当呈现页面时,该占位符将被替换为不同的内容类型(例如,十六进制代码,滑块,图像......)。占位符的替换有点复杂并且具有一些附加功能(例如,定义默认值,用正确语言的内容替换占位符,......)。因此,我创建了一个带有"占位符过滤器"的枝条扩展。此函数应获取正确的内容以替换占位符并处理其他功能。因为内容类型是如此不同有一些 - 让它调用"插件" - 对于每个包含用于在控制器中呈现内容的逻辑的内容类型。

现在我的问题:

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

我的想法到现在为止:

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

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

因此在树枝中调用控制器动作似乎没有问题。但是我需要这个函数 - 在一个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中调用控制器动作而不将控制器定义为服务?或者我应该重新考虑整个解决方案吗?

2 个答案:

答案 0 :(得分:1)

也许你可以定义一个ViewListener并让你的控制器返回你想要的html而不是在控制器上由$ this-> render返回的Response。

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

我真的觉得整个系统设置这样会非常hacky并且很难长期维护,所以我建议重新考虑它

答案 1 :(得分:0)

几个小时后"思考问题"我发现主要问题的简单答案。当我在我的过滤器函数中包含Twig_environment时(参见https://www.robinvdvleuten.nl/blog/rendering-templates-in-a-twig-extension/),我可以访问twig render() - 函数。该函数适用于模板和字符串。因此,在没有服务的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为模板渲染定义了额外的辅助函数,这就是我想用我的filter-function来替换特殊的占位符内容)。

也许这不是最好的做法,不包括我的插件控制器作为服务,但我不知道这样的插件控制器的缺点,直到现在 - 当你知道一个:请告诉我,因为我开放学习"如何让它变得更好" ; - )