我想创建一个事件监听器,它将db查询的一些结果添加到所有symfony动作
例如:
class BlogController extends Controller
{
/**
* @Route("/blog/")
* @Template()
*/
public function indexAction()
{
....
return array(
'entries' => $posts
);
}
}
这个控制器正在将entries
变量传递给视图,我想创建一个侦听器,它获取所有动作的返回值,并为返回的数组注入另一个索引(例如)
array(
'entries' => $posts,
'categories' => $categories
);
所以我可以从应用程序视图中的任何位置调用$categories
var
我希望你们的问题很清楚。提前谢谢。
答案 0 :(得分:1)
您应该考虑创建global variable或twig extension以在模板中提供类别,您无法通过使用事件来执行此操作(因为模板已在内部解析控制器,而不是之前/之后)
答案 1 :(得分:1)
这种方法虽然在某些框架中有效且常用,但在Symfony中并不常见,因为它比HMVC架构更适合MVC。
我建议你使用不同的结果:
不是向每个控制器返回添加参数,而是渲染另一个控制器,该控制器只返回您要显示的内容的子视图。简单的例子:
// article/index.html.twig
<div class="category-bar">{{ render(controller('MyVendorMyBundle:CategoryController:bar')) }}</div>
<div class="article-list">
{% for article in articles %>
{# Print article here #}
{% endfor %}
</div>
// CategoryController
class CategoryController extends Controller
{
/**
* @Template
*/
public function barAction()
{
return ['categories' => $this->fetchCategoriesSomehow()];
}
}
因此,当您渲染文章列表操作时,twig将触发子请求以在其上方呈现类别栏。
此外,如果您不喜欢制作子请求,则不会阻止您创建一个枝条扩展服务,该服务将为您提取类别和渲染模板。
答案 2 :(得分:1)
在大多数情况下,我会使用@Wouter J的建议并创建一个枝条扩展或全局变量。
但是,你想要做的事实上是可能的(无论这是否是正确的解决方案)。
@Template annotation有一个vars属性,可让您指定应将请求中的哪些属性传递给模板:
/**
* @ParamConverter("post", class="SensioBlogBundle:Post")
* @Template("SensioBlogBundle:Post:show.html.twig", vars={"post"})
*/
public function showAction()
{
}
请注意,您可以设置请求属性:
$request->attributes->set('categories', []);
因此,您可以实现一个侦听器,该侦听器会在请求上设置categories属性,而不是在vars
注释上配置@Template
:
/**
* @Template("SensioBlogBundle:Post:show.html.twig", vars={"categories"})
*/
public function showAction(Post $post)
{
}
查看SensioFrameworkExtraBundle中的TemplateListener以获取更多信息。 kernel.controller
上的听众defines template vars和kernel.view
上的uses them to render the view。
如果您的监听器是在vars
之后注册的,则可以避免在注释上定义TemplateListener::onController()
。它必须为_template_vars
请求属性添加类别。
答案 3 :(得分:0)
使用Twig扩展来创建将返回可用类别列表的函数
<?php
class CategoriesExtension extends \Twig_Extension
{
public function getFunctions()
{
return [
new \Twig_SimpleFunction('getCategories', [$this, 'getCategoriesList'])
];
}
/**
* @return null|string
*/
public function getCategoriesList()
{
return CategoryQuery::create()->find();
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'list_categories';
}
}
如果您想在查询中执行某些条件,可以将参数传递给函数。
答案 4 :(得分:-1)
诀窍是在你的监听器中获取twig服务,然后使用addGlobal添加你的类别
namespace Cerad\Bundle\CoreBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpKernel\HttpKernel;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MyEventListener extends ContainerAware implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(
KernelEvents::CONTROLLER => array(
array('doCategories', -1100),
);
}
public function doCategories(FilterControllerEvent $eventx)
{
// Query your categories
$categories = array('cat1','cat2');
// Make them available to all twig templates
$twig = $this->container->get('twig');
$twig->addGlobal('categories',$categories);
}
# services.yml
cerad_core__my__event_listener:
class: '%cerad_core__my__event_listener__class%'
calls:
- [setContainer, ['@service_container']]
tags:
- { name: kernel.event_subscriber }