Symfony2:使用侦听器更改渲染视图
Posted
技术标签:
【中文标题】Symfony2:使用侦听器更改渲染视图【英文标题】:Symfony2: Change rendered view with a listener 【发布时间】:2012-08-15 13:52:42 【问题描述】:我想在我的 Symfony2 项目中在不同的上下文中呈现不同的视图。 我正在为相同的操作使用多个路由,并且我想呈现不同的页面(视图)但使用相同的控制器。 例如我有:
@Route("/articles/show", name="articles_show")
@Route("/mobile/articles/show", name="mobile_articles_show")
两条路线都使用相同的操作:ArticlesController:showAction(),但应该呈现2个不同的模板(移动用户和普通用户)。
show.html.twig
mobile.show.html.twig
我不想在我的控制器中使用 if 语句或其他任何东西,所以我创建了一个侦听器(类似于 preExecute 函数)
这是定义我的 listener
的部分或我的 config.ymlservices:
controller.pre_execute_listener:
class: MyProject\MyBundle\Listener\ControllerListener
arguments: ["@security.context", "@doctrine", "@router", "@session"]
tags:- name: kernel.event_listener, event: kernel.controller, method: preExecute
我正在考虑在侦听器 preExecute 函数中做类似的事情:
if(substr($route,0,7) == 'mobile_')
$view = 'mobile.'.$view;
很遗憾,在渲染之前,我找不到获取 $view 或“即时”更新视图的方法。
我希望我的问题足够清楚,在此先感谢,欢迎任何想法:)
J.
【问题讨论】:
【参考方案1】:这里是解决方案:
首先我必须听kernel.view,而不是kernel.controller。
然后我使用“@templating”服务(感谢 Marko Jovanovic 的提示)
这是我的新 config.yml:
services:
controller.pre_execute_listener:
class: MyProject\MyBundle\Listener\ControllerListener
arguments: ["@templating"]
tags:
- name: kernel.event_listener, event: kernel.view, method: preExecute
终于来了我的监听器preExecute函数
public function preExecute(\Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent $event)
//result returned by the controller
$data = $event->getControllerResult();
/* @var $request \Symfony\Component\HttpFoundation\Request */
$request = $event->getRequest();
$template = $request->get('_template');
$route = $request->get('_route');
if(substr($route,0,7) == 'mobile_')
$newTemplate = str_replace('html.twig','mobile.html.twig',$template);
//Overwrite original template with the mobile one
$response = $this->templating->renderResponse($newTemplate, $data);
$event->setResponse($response);
希望这会有所帮助!
J.
【讨论】:
【参考方案2】:值得注意的是:如果您直接返回 Response
对象(例如,当您调用 $this->render()
时),接受的解决方案实际上不起作用,因为在这种情况下不会触发 kernel.view
事件:
如果控制器没有返回 Response 对象,那么内核会调度另一个事件 -
kernel.view
。——见Symfony's HTTP Kernel Docs
我无法解决这个问题,但找到了针对同一问题的另一个有趣的解决方案: 您可以像 ZenstruckMobileBundle 那样简单地扩展 twig 的渲染引擎,或者像 LiipThemeBundle 那样编写自己的文件定位器。
[edit:] 或者,您也可以覆盖TemplateNameParser
。
【讨论】:
【参考方案3】:您可以添加“@templating”服务作为 controller.pre_execute_listener 的参数。
【讨论】:
该服务帮助我渲染一个新的,而不是获取当前的。我找不到获取“当前”视图的方法。 哦,抱歉,我只是假设 @template 包含当前名称的名称(我真傻):(。无论如何,我看到你解决了问题,所以你可以发布答案自己接受它。PS如果您需要替代模板的替代方法,请参阅我关于此主题的答案***.com/questions/8257676/…【参考方案4】:您的设备检测似乎是在您到达路线之前完成的,所以我敢打赌,由于在请求之前进行了一些检测,您希望移动用户会使用移动路线,这似乎在每个模板中处理起来都很痛苦,并且网址生成。
在之前或之后检测设备可能会更好(感谢Categorizr 或some nice apache configuration),但不依赖于使用的路由进行移动检测。
Categorizr 与调用模板渲染的that way 的集成可能会很好。
然后使用a nice bundle for using the right templates/themes 或using one which provides some more generic functions
【讨论】:
以上是关于Symfony2:使用侦听器更改渲染视图的主要内容,如果未能解决你的问题,请参考以下文章