如何创建在symfony2中注入视图数据的事件侦听器?

时间:2014-05-29 20:46:25

标签: symfony

我想创建一个事件监听器,它将db查询的一些结果添加到所有symfony动作

例如:

class BlogController extends Controller
{
    /**
     * @Route("/blog/")
     * @Template()
     */
    public function indexAction()
    {
        ....

        return array(
            'entries' => $posts
        );
    }
}

这个控制器正在将entries变量传递给视图,我想创建一个侦听器,它获取所有动作的返回值,并为返回的数组注入另一个索引(例如)

array(
    'entries' => $posts,
    'categories' => $categories
);

所以我可以从应用程序视图中的任何位置调用$categories var

我希望你们的问题很清楚。提前谢谢。

5 个答案:

答案 0 :(得分:1)

您应该考虑创建global variabletwig 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 varskernel.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 }