Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 83232f8

Browse filesBrowse files
committed
feature #27675 [DoctrineBridge] always load event listeners lazy via ServiceLocator (dmaicher)
This PR was squashed before being merged into the 4.2-dev branch (closes #27675). Discussion ---------- [DoctrineBridge] always load event listeners lazy via ServiceLocator | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes/no | Tests pass? | yes | Fixed tickets | #27661 | License | MIT | Doc PR | symfony/symfony-docs#9973 As described in #27661 this PR suggests to always load doctrine event listeners lazily from a service locator instead of the full service container. If we agree to move forward I could tackle the remaining todos: - [x] update UPGRADE.md - [x] documentation PR - [x] tested on real app Commits ------- 130ec05 [DoctrineBridge] always load event listeners lazy via ServiceLocator
2 parents d3a43b1 + 130ec05 commit 83232f8
Copy full SHA for 83232f8

File tree

Expand file treeCollapse file tree

3 files changed

+71
-27
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+71
-27
lines changed

‎UPGRADE-4.2.md

Copy file name to clipboardExpand all lines: UPGRADE-4.2.md
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,9 @@ SecurityBundle
5252
`security.authentication.trust_resolver.rememberme_class` parameters to define
5353
the token classes is deprecated. To use
5454
custom tokens extend the existing AnonymousToken and RememberMeToken.
55+
56+
DoctrineBridge
57+
--------------
58+
59+
* The `lazy` attribute on `doctrine.event_listener` tags was removed.
60+
Listeners are now lazy by default. So any `lazy` attributes can safely be removed from those tags.

‎src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPass.php
+11-6Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass;
1313

1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
15+
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1718
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -80,10 +81,10 @@ private function addTaggedListeners(ContainerBuilder $container)
8081
{
8182
$listenerTag = $this->tagPrefix.'.event_listener';
8283
$taggedListeners = $this->findAndSortTags($listenerTag, $container);
84+
$listenerRefs = array();
8385

8486
foreach ($taggedListeners as $taggedListener) {
8587
list($id, $tag) = $taggedListener;
86-
$taggedListenerDef = $container->getDefinition($id);
8788
if (!isset($tag['event'])) {
8889
throw new InvalidArgumentException(sprintf('Doctrine event listener "%s" must specify the "event" attribute.', $id));
8990
}
@@ -93,15 +94,19 @@ private function addTaggedListeners(ContainerBuilder $container)
9394
if (!isset($this->connections[$con])) {
9495
throw new RuntimeException(sprintf('The Doctrine connection "%s" referenced in service "%s" does not exist. Available connections names: %s', $con, $id, implode(', ', array_keys($this->connections))));
9596
}
96-
97-
if ($lazy = !empty($tag['lazy'])) {
98-
$taggedListenerDef->setPublic(true);
99-
}
97+
$listenerRefs[$con][$id] = new Reference($id);
10098

10199
// we add one call per event per service so we have the correct order
102-
$this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', array(array($tag['event']), $lazy ? $id : new Reference($id)));
100+
$this->getEventManagerDef($container, $con)->addMethodCall('addEventListener', array(array($tag['event']), $id));
103101
}
104102
}
103+
104+
// replace service container argument of event managers with smaller service locator
105+
// so services can even remain private
106+
foreach ($listenerRefs as $connection => $refs) {
107+
$this->getEventManagerDef($container, $connection)
108+
->replaceArgument(0, ServiceLocatorTagPass::register($container, $refs));
109+
}
105110
}
106111

107112
private function getEventManagerDef(ContainerBuilder $container, $name)

‎src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php
+54-21Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Bridge\Doctrine\DependencyInjection\CompilerPass\RegisterEventListenersAndSubscribersPass;
16+
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
1617
use Symfony\Component\DependencyInjection\ContainerBuilder;
1718
use Symfony\Component\DependencyInjection\Definition;
1819
use Symfony\Component\DependencyInjection\Reference;
20+
use Symfony\Component\DependencyInjection\ServiceLocator;
1921

2022
class RegisterEventListenersAndSubscribersPassTest extends TestCase
2123
{
@@ -68,7 +70,6 @@ public function testProcessEventListenersWithPriorities()
6870
->addTag('doctrine.event_listener', array(
6971
'event' => 'foo_bar',
7072
'priority' => 3,
71-
'lazy' => true,
7273
))
7374
;
7475
$container
@@ -86,25 +87,30 @@ public function testProcessEventListenersWithPriorities()
8687
;
8788

8889
$this->process($container);
89-
$methodCalls = $container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls();
90+
$eventManagerDef = $container->getDefinition('doctrine.dbal.default_connection.event_manager');
91+
$methodCalls = $eventManagerDef->getMethodCalls();
9092

9193
$this->assertEquals(
9294
array(
93-
array('addEventListener', array(array('foo_bar'), new Reference('c'))),
94-
array('addEventListener', array(array('foo_bar'), new Reference('a'))),
95-
array('addEventListener', array(array('bar'), new Reference('a'))),
96-
array('addEventListener', array(array('foo'), new Reference('b'))),
97-
array('addEventListener', array(array('foo'), new Reference('a'))),
95+
array('addEventListener', array(array('foo_bar'), 'c')),
96+
array('addEventListener', array(array('foo_bar'), 'a')),
97+
array('addEventListener', array(array('bar'), 'a')),
98+
array('addEventListener', array(array('foo'), 'b')),
99+
array('addEventListener', array(array('foo'), 'a')),
98100
),
99101
$methodCalls
100102
);
101103

102-
// not lazy so must be reference
103-
$this->assertInstanceOf('Symfony\Component\DependencyInjection\Reference', $methodCalls[0][1][1]);
104-
105-
// lazy so id instead of reference and must mark service public
106-
$this->assertSame('a', $methodCalls[1][1][1]);
107-
$this->assertTrue($container->getDefinition('a')->isPublic());
104+
$serviceLocatorDef = $container->getDefinition((string) $eventManagerDef->getArgument(0));
105+
$this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass());
106+
$this->assertEquals(
107+
array(
108+
'c' => new ServiceClosureArgument(new Reference('c')),
109+
'a' => new ServiceClosureArgument(new Reference('a')),
110+
'b' => new ServiceClosureArgument(new Reference('b')),
111+
),
112+
$serviceLocatorDef->getArgument(0)
113+
);
108114
}
109115

110116
public function testProcessEventListenersWithMultipleConnections()
@@ -136,20 +142,45 @@ public function testProcessEventListenersWithMultipleConnections()
136142

137143
$this->process($container);
138144

145+
$eventManagerDef = $container->getDefinition('doctrine.dbal.default_connection.event_manager');
146+
147+
// first connection
139148
$this->assertEquals(
140149
array(
141-
array('addEventListener', array(array('onFlush'), new Reference('a'))),
142-
array('addEventListener', array(array('onFlush'), new Reference('b'))),
150+
array('addEventListener', array(array('onFlush'), 'a')),
151+
array('addEventListener', array(array('onFlush'), 'b')),
143152
),
144-
$container->getDefinition('doctrine.dbal.default_connection.event_manager')->getMethodCalls()
153+
$eventManagerDef->getMethodCalls()
145154
);
146155

156+
$serviceLocatorDef = $container->getDefinition((string) $eventManagerDef->getArgument(0));
157+
$this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass());
147158
$this->assertEquals(
148159
array(
149-
array('addEventListener', array(array('onFlush'), new Reference('a'))),
150-
array('addEventListener', array(array('onFlush'), new Reference('c'))),
160+
'a' => new ServiceClosureArgument(new Reference('a')),
161+
'b' => new ServiceClosureArgument(new Reference('b')),
151162
),
152-
$container->getDefinition('doctrine.dbal.second_connection.event_manager')->getMethodCalls()
163+
$serviceLocatorDef->getArgument(0)
164+
);
165+
166+
// second connection
167+
$secondEventManagerDef = $container->getDefinition('doctrine.dbal.second_connection.event_manager');
168+
$this->assertEquals(
169+
array(
170+
array('addEventListener', array(array('onFlush'), 'a')),
171+
array('addEventListener', array(array('onFlush'), 'c')),
172+
),
173+
$secondEventManagerDef->getMethodCalls()
174+
);
175+
176+
$serviceLocatorDef = $container->getDefinition((string) $secondEventManagerDef->getArgument(0));
177+
$this->assertSame(ServiceLocator::class, $serviceLocatorDef->getClass());
178+
$this->assertEquals(
179+
array(
180+
'a' => new ServiceClosureArgument(new Reference('a')),
181+
'c' => new ServiceClosureArgument(new Reference('c')),
182+
),
183+
$serviceLocatorDef->getArgument(0)
153184
);
154185
}
155186

@@ -269,11 +300,13 @@ private function createBuilder($multipleConnections = false)
269300

270301
$connections = array('default' => 'doctrine.dbal.default_connection');
271302

272-
$container->register('doctrine.dbal.default_connection.event_manager', 'stdClass');
303+
$container->register('doctrine.dbal.default_connection.event_manager', 'stdClass')
304+
->addArgument(new Reference('service_container'));
273305
$container->register('doctrine.dbal.default_connection', 'stdClass');
274306

275307
if ($multipleConnections) {
276-
$container->register('doctrine.dbal.second_connection.event_manager', 'stdClass');
308+
$container->register('doctrine.dbal.second_connection.event_manager', 'stdClass')
309+
->addArgument(new Reference('service_container'));
277310
$container->register('doctrine.dbal.second_connection', 'stdClass');
278311
$connections['second'] = 'doctrine.dbal.second_connection';
279312
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.