Skip to content

Commit e62a390

Browse files
bug #20566 [DI] Initialize properties before method calls (ro0NL)
This PR was squashed before being merged into the 2.7 branch (closes #20566). Discussion ---------- [DI] Initialize properties before method calls | Q | A | ------------- | --- | Branch? | 2.7 | Bug fix? | yes-ish | New feature? | no | BC breaks? | not sure | Deprecations? | no | Tests pass? | not yet (only dumps seem to fail) | Fixed tickets | comma-separated list of tickets fixed by the PR, if any | License | MIT | Doc PR | reference to the documentation PR, if any Given ```yml services: handler: class: AppBundle\Handler properties: debug: '%kernel.debug%' calls: - [handle] ``` I totally expected `Handler::$debug` to be set before `Handler::handle` is called. It was not.. and it's really annoying :) Commits ------- 0af433b [DI] Initialize properties before method calls
2 parents 3eb8a34 + 0af433b commit e62a390

File tree

7 files changed

+63
-13
lines changed

7 files changed

+63
-13
lines changed

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -902,15 +902,15 @@ public function createService(Definition $definition, $id, $tryProxy = true)
902902
$this->shareService($definition, $service, $id);
903903
}
904904

905-
foreach ($definition->getMethodCalls() as $call) {
906-
$this->callMethod($service, $call);
907-
}
908-
909905
$properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())));
910906
foreach ($properties as $name => $value) {
911907
$service->$name = $value;
912908
}
913909

910+
foreach ($definition->getMethodCalls() as $call) {
911+
$this->callMethod($service, $call);
912+
}
913+
914914
if ($callable = $definition->getConfigurator()) {
915915
if (is_array($callable)) {
916916
$callable[0] = $parameterBag->resolveValue($callable[0]);

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,8 @@ private function addServiceInlinedDefinitions($id, $definition)
335335
$code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');
336336

337337
if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
338-
$code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
339338
$code .= $this->addServiceProperties(null, $sDefinition, $name);
339+
$code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
340340
$code .= $this->addServiceConfigurator(null, $sDefinition, $name);
341341
}
342342

@@ -507,8 +507,8 @@ private function addServiceInlinedDefinitionsSetup($id, Definition $definition)
507507
}
508508

509509
$name = (string) $this->definitionVariables->offsetGet($iDefinition);
510-
$code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
511510
$code .= $this->addServiceProperties(null, $iDefinition, $name);
511+
$code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
512512
$code .= $this->addServiceConfigurator(null, $iDefinition, $name);
513513
}
514514

@@ -663,8 +663,8 @@ private function addService($id, Definition $definition)
663663
$this->addServiceInlinedDefinitions($id, $definition).
664664
$this->addServiceInstance($id, $definition).
665665
$this->addServiceInlinedDefinitionsSetup($id, $definition).
666-
$this->addServiceMethodCalls($id, $definition).
667666
$this->addServiceProperties($id, $definition).
667+
$this->addServiceMethodCalls($id, $definition).
668668
$this->addServiceConfigurator($id, $definition).
669669
$this->addServiceReturn($id, $definition)
670670
;

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

+14
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,20 @@ public function testLazyLoadedService()
819819

820820
$this->assertTrue($classInList);
821821
}
822+
823+
public function testInitializePropertiesBeforeMethodCalls()
824+
{
825+
$container = new ContainerBuilder();
826+
$container->register('foo', 'stdClass');
827+
$container->register('bar', 'MethodCallClass')
828+
->setProperty('simple', 'bar')
829+
->setProperty('complex', new Reference('foo'))
830+
->addMethodCall('callMe');
831+
832+
$container->compile();
833+
834+
$this->assertTrue($container->get('bar')->callPassed(), '->compile() initializes properties before method calls');
835+
}
822836
}
823837

824838
class FooClass

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

+19
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,23 @@ public function testInlinedDefinitionReferencingServiceContainer()
267267
$dumper = new PhpDumper($container);
268268
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services13.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container');
269269
}
270+
271+
public function testInitializePropertiesBeforeMethodCalls()
272+
{
273+
require_once self::$fixturesPath.'/includes/classes.php';
274+
275+
$container = new ContainerBuilder();
276+
$container->register('foo', 'stdClass');
277+
$container->register('bar', 'MethodCallClass')
278+
->setProperty('simple', 'bar')
279+
->setProperty('complex', new Reference('foo'))
280+
->addMethodCall('callMe');
281+
$container->compile();
282+
283+
$dumper = new PhpDumper($container);
284+
eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls')));
285+
286+
$container = new \Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls();
287+
$this->assertTrue($container->get('bar')->callPassed(), '->dump() initializes properties before method calls');
288+
}
270289
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php

+17
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,20 @@ public function __construct(BarClass $bar)
5959
$this->bar = $bar;
6060
}
6161
}
62+
63+
class MethodCallClass
64+
{
65+
public $simple;
66+
public $complex;
67+
private $callPassed = false;
68+
69+
public function callMe()
70+
{
71+
$this->callPassed = is_scalar($this->simple) && is_object($this->complex);
72+
}
73+
74+
public function callPassed()
75+
{
76+
return $this->callPassed;
77+
}
78+
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,11 @@ protected function getFooService()
170170

171171
$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this);
172172

173-
$instance->setBar($this->get('bar'));
174-
$instance->initialize();
175173
$instance->foo = 'bar';
176174
$instance->moo = $a;
177175
$instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo'));
176+
$instance->setBar($this->get('bar'));
177+
$instance->initialize();
178178
sc_configure($instance);
179179

180180
return $instance;
@@ -333,8 +333,8 @@ protected function getInlinedService()
333333
{
334334
$this->services['inlined'] = $instance = new \Bar();
335335

336-
$instance->setBaz($this->get('baz'));
337336
$instance->pub = 'pub';
337+
$instance->setBaz($this->get('baz'));
338338

339339
return $instance;
340340
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,11 @@ protected function getFooService()
179179

180180
$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this);
181181

182-
$instance->setBar($this->get('bar'));
183-
$instance->initialize();
184182
$instance->foo = 'bar';
185183
$instance->moo = $a;
186184
$instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar');
185+
$instance->setBar($this->get('bar'));
186+
$instance->initialize();
187187
sc_configure($instance);
188188

189189
return $instance;
@@ -230,8 +230,8 @@ protected function getFooWithInlineService()
230230

231231
$this->services['foo_with_inline'] = $instance = new \Foo();
232232

233-
$a->setBaz($this->get('baz'));
234233
$a->pub = 'pub';
234+
$a->setBaz($this->get('baz'));
235235

236236
$instance->setBar($a);
237237

0 commit comments

Comments
 (0)