-
-
Notifications
You must be signed in to change notification settings - Fork 9.7k
Description
Hi !
In Symfony 3.1.1 (and maybe other versions), if i have this 2 listeners (this is just an example, with @service_container in arguments, i know) :
services:
last_listener:
class: Foo\LastServiceListener
arguments: [ '%foo.bar%' ]
tags:
- { name: kernel.event_listener, event: kernel.request, priority: 17 }
first_listener:
class: Foo\FirstServiceListener
arguments: [ '@service_container' ]
tags:
- { name: kernel.event_listener, event: kernel.request, priority: 16 }
namespace Huttosoft\Back\Bundle\ContextBundle\EventListener;
use Symfony\Component\DependencyInjection\ContainerInterface;
class FirstServiceListener
{
/** @var ContainerInterface */
protected $container;
/**
* @param ContainerInterface $container
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function onKernelRequest()
{
$this->container->setParameter('foo.bar', uniqid());
}
}
namespace Huttosoft\Back\Bundle\ContextBundle\EventListener;
class LastServiceListener
{
/**
* @param bool $fooBar
*/
public function __construct($fooBar)
{
}
}
Listeners priority aren't taken into account for __construct() call, and more generally, "all" listeners __construct() methods are called, "before" any onKernelEvent methods is called.
In var/cache/classes.php, in lazyLoad($eventName) method :
protected function lazyLoad($eventName)
{
var_dump($eventName, $this->listenerIds[$eventName]);
exit();
if (isset($this->listenerIds[$eventName])) {
foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) {
$listener = $this->container->get($serviceId);
$key = $serviceId.'.'.$method;
if (!isset($this->listeners[$eventName][$key])) {
$this->addListener($eventName, array($listener, $method), $priority);
} elseif ($listener !== $this->listeners[$eventName][$key]) {
parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
$this->addListener($eventName, array($listener, $method), $priority);
}
$this->listeners[$eventName][$key] = $listener;
}
}
Output, without useless listeners :
string(14) "kernel.request"
array(19) {
[2]=>
array(3) {
[0]=>
string(13) "last_listener"
[1]=>
string(15) "onKernelRequest"
[2]=>
int(17)
}
[3]=>
array(3) {
[0]=>
string(14) "first_listener"
[1]=>
string(15) "onKernelRequest"
[2]=>
int(16)
}
}
First problem : __construct() are not called by priority, but by registration in Container.
Second problem : FirstListener::onKernelRequest() can't do something required in LastListener::__construct().
I was waiting for this call tree :
- FirstService::__construct()
- FirstService::onKernelRequest()
- LastService::__construct()
- LastService::onKernelRequest()
But i have this one :
- LastService::__construct()
- FirstService::__construct()
- FirstService::onKernelRequest()
- LastService::onKernelRequest()
I know it's a huge change to lazy call __construct(), but could you at least call it by priority order, instead of Container registration order ?
Thanks !