我试图从symfony2中的事件监听器发送var来查看,但我已经堆叠了.
1)这可能吗?
2)使用什么内核事件(kernel.view或kernel.request)?
3)最后如何发送一些var来查看?
我最好的猜测是,我必须从控制器延长返回,然后让控制器完成他的工作.
我需要发送一些对象(实体).
我看到了几种处理这个问题的方法.
kernel.request
侦听器添加全局变量我们的想法是在kernel.request
事件发生后直接添加一个全局变量.
services.yml
services: class: Acme\FooBundle\Listener\MyListener arguments: - @twig tags: - name: kernel.event_listener event: kernel.request method: onKernelRequest
MyListener
class MyListener { protected $twig; public function __construct(\Twig_Environment $twig) { $this->twig = $twig; } public function onKernelRequest(GetResponseEvent $event) { $myVar = 'foo'; // Process data $this->twig->addGlobal('myvar', $myVar); } }
您现在可以随时使用它
{{ myvar }}
kernel.view
听众首先,您需要了解何时kernel.view
被调用.仅当控制器的返回不是Response对象的实例时才会调用它.
那说,做
// Acme/FooBundle/FooController#fooAction return $this->render();
返回一个Response对象,因此kernel.view
不会被调用.
我们的想法是让所有控制器返回一个数据数组,就像@Template
要求一样.
// Acme/FooBundle/FooController#fooAction return array( 'template' => 'AcmeFooBundle:Foo:foo.html.twig', 'data' => array( 'entity' => $entity ) );
由于您已经拥有服务定义,因此您只需在服务声明中添加一些要求即可.
您需要该@templating
服务来呈现数据.
您需要将自己设置为kernel.view
侦听器
// Acme/FooBundle/Resources/config/services.yml services: acme_foo.my_listener: class: Acme\FooBundle\Listener\MyListener arguments: - @templating tags: - name: kernel.event_listener event: kernel.request method: onKernelRequest - name: kernel.event_listener event: kernel.view method: onKernelView
// Acme/FooBundle/Listener/MyListener.php use Symfony\Component\Templating\EngineInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; class MyListener { protected $templating; protected $myVar; public function __construct(EngineInterface $templating) { $this->templating = $templating; } public function getMyVar() { return $this->myVar; } public function onKernelRequest(GetResponseEvent $event) { $this->myVar = ""; // Process MyVar data } public function onKernelView(GetResponseForControllerResultEvent $event) { $result = $event->getControllerResult(); if (null === $this->myVar || !isset($result['template']) || !isset($result['data'])) { return; } $data = array_merge($result['data'], array('myvar' => $this->myVar)); $rendered = $this->templating->render($result['template'], $data); $event->setResponse(new Response($rendered)); } }
你有.监听器正在创建一个新的响应,将您的自定义定义添加myvar
到他呈现的任何模板中.
另一种方法是创建TWIG扩展.在下面的例子中,我假设MyListener
定义与上面相同.
根据上面给出的文档,您只需创建一个简单的扩展类.
// Acme/FooBundle/Resources/config/services.yml services: acme_foo.my_listener: class: Acme\FooBundle\Listener\MyListener tags: - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest } acme_foo.my_extension: class: Acme\FooBundle\Extension\MyExtension arguments: - @acme_foo.my_listener tags: - { name: twig.extension }
就像在文档中一样,我们将创建一个简单的函数.
// Acme/FooBundle/Extension/MyExtension.php use Acme\FooBundle\Listener\MyListener; class MyExtension extends \Twig_Extension { protected $listener; public function __construct(MyListener $listener) { $this->listener = $listener; } public function getName() { return 'my_extension'; } public function getFunctions() { return array( 'myvar' => new \Twig_Function_Method($this, 'getMyVar') ); } public function getMyVar() { return $this->listener->getMyVar(); } }
然后你可以在任何视图中使用它
{{ myvar() }}
我不喜欢这个想法,但这是另一种选择.您只需要创建一个BaseController
将覆盖默认render
方法.
// Acme/FooBundle/Controller/BaseController.php abstract class BaseController extends Controller { public function render($view, array $parameters = array(), Response $response = null) { $parameters = array_merge( $parameters, array( 'myvar' => $this->get('my_listener')->getMyVar() ) ); return parent::render($view, $parameters, $response); } }