4 * This file is part of the Symfony package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Symfony\Component\DependencyInjection\Tests;
14 require_once __DIR__.'/Fixtures/includes/classes.php';
15 require_once __DIR__.'/Fixtures/includes/ProjectExtension.php';
17 use PHPUnit\Framework\TestCase;
18 use Psr\Container\ContainerInterface as PsrContainerInterface;
19 use Symfony\Component\Config\Resource\ComposerResource;
20 use Symfony\Component\Config\Resource\ResourceInterface;
21 use Symfony\Component\Config\Resource\DirectoryResource;
22 use Symfony\Component\DependencyInjection\Alias;
23 use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
24 use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
25 use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
26 use Symfony\Component\DependencyInjection\ChildDefinition;
27 use Symfony\Component\DependencyInjection\Compiler\PassConfig;
28 use Symfony\Component\DependencyInjection\ContainerBuilder;
29 use Symfony\Component\DependencyInjection\ContainerInterface;
30 use Symfony\Component\DependencyInjection\Definition;
31 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
32 use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
33 use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
34 use Symfony\Component\DependencyInjection\Reference;
35 use Symfony\Component\DependencyInjection\Tests\Fixtures\SimilarArgumentsDummy;
36 use Symfony\Component\DependencyInjection\TypedReference;
37 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
38 use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
39 use Symfony\Component\Config\Resource\FileResource;
40 use Symfony\Component\DependencyInjection\ServiceLocator;
41 use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
42 use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass;
43 use Symfony\Component\ExpressionLanguage\Expression;
45 class ContainerBuilderTest extends TestCase
47 public function testDefaultRegisteredDefinitions()
49 $builder = new ContainerBuilder();
51 $this->assertCount(1, $builder->getDefinitions());
52 $this->assertTrue($builder->hasDefinition('service_container'));
54 $definition = $builder->getDefinition('service_container');
55 $this->assertInstanceOf(Definition::class, $definition);
56 $this->assertTrue($definition->isSynthetic());
57 $this->assertSame(ContainerInterface::class, $definition->getClass());
58 $this->assertTrue($builder->hasAlias(PsrContainerInterface::class));
59 $this->assertTrue($builder->hasAlias(ContainerInterface::class));
62 public function testDefinitions()
64 $builder = new ContainerBuilder();
66 'foo' => new Definition('Bar\FooClass'),
67 'bar' => new Definition('BarClass'),
69 $builder->setDefinitions($definitions);
70 $this->assertEquals($definitions, $builder->getDefinitions(), '->setDefinitions() sets the service definitions');
71 $this->assertTrue($builder->hasDefinition('foo'), '->hasDefinition() returns true if a service definition exists');
72 $this->assertFalse($builder->hasDefinition('foobar'), '->hasDefinition() returns false if a service definition does not exist');
74 $builder->setDefinition('foobar', $foo = new Definition('FooBarClass'));
75 $this->assertEquals($foo, $builder->getDefinition('foobar'), '->getDefinition() returns a service definition if defined');
76 $this->assertSame($builder->setDefinition('foobar', $foo = new Definition('FooBarClass')), $foo, '->setDefinition() implements a fluid interface by returning the service reference');
78 $builder->addDefinitions($defs = array('foobar' => new Definition('FooBarClass')));
79 $this->assertEquals(array_merge($definitions, $defs), $builder->getDefinitions(), '->addDefinitions() adds the service definitions');
82 $builder->getDefinition('baz');
83 $this->fail('->getDefinition() throws a ServiceNotFoundException if the service definition does not exist');
84 } catch (ServiceNotFoundException $e) {
85 $this->assertEquals('You have requested a non-existent service "baz".', $e->getMessage(), '->getDefinition() throws a ServiceNotFoundException if the service definition does not exist');
91 * @expectedDeprecation The "deprecated_foo" service is deprecated. You should stop using it, as it will soon be removed.
93 public function testCreateDeprecatedService()
95 $definition = new Definition('stdClass');
96 $definition->setDeprecated(true);
98 $builder = new ContainerBuilder();
99 $builder->setDefinition('deprecated_foo', $definition);
100 $builder->get('deprecated_foo');
103 public function testRegister()
105 $builder = new ContainerBuilder();
106 $builder->register('foo', 'Bar\FooClass');
107 $this->assertTrue($builder->hasDefinition('foo'), '->register() registers a new service definition');
108 $this->assertInstanceOf('Symfony\Component\DependencyInjection\Definition', $builder->getDefinition('foo'), '->register() returns the newly created Definition instance');
111 public function testAutowire()
113 $builder = new ContainerBuilder();
114 $builder->autowire('foo', 'Bar\FooClass');
116 $this->assertTrue($builder->hasDefinition('foo'), '->autowire() registers a new service definition');
117 $this->assertTrue($builder->getDefinition('foo')->isAutowired(), '->autowire() creates autowired definitions');
120 public function testHas()
122 $builder = new ContainerBuilder();
123 $this->assertFalse($builder->has('foo'), '->has() returns false if the service does not exist');
124 $builder->register('foo', 'Bar\FooClass');
125 $this->assertTrue($builder->has('foo'), '->has() returns true if a service definition exists');
126 $builder->set('bar', new \stdClass());
127 $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists');
131 * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException
132 * @expectedExceptionMessage You have requested a non-existent service "foo".
134 public function testGetThrowsExceptionIfServiceDoesNotExist()
136 $builder = new ContainerBuilder();
137 $builder->get('foo');
140 public function testGetReturnsNullIfServiceDoesNotExistAndInvalidReferenceIsUsed()
142 $builder = new ContainerBuilder();
144 $this->assertNull($builder->get('foo', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service does not exist and NULL_ON_INVALID_REFERENCE is passed as a second argument');
148 * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
150 public function testGetThrowsCircularReferenceExceptionIfServiceHasReferenceToItself()
152 $builder = new ContainerBuilder();
153 $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz')));
154 $builder->get('baz');
157 public function testGetReturnsSameInstanceWhenServiceIsShared()
159 $builder = new ContainerBuilder();
160 $builder->register('bar', 'stdClass');
162 $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared');
165 public function testGetCreatesServiceBasedOnDefinition()
167 $builder = new ContainerBuilder();
168 $builder->register('foo', 'stdClass');
170 $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id');
173 public function testGetReturnsRegisteredService()
175 $builder = new ContainerBuilder();
176 $builder->set('bar', $bar = new \stdClass());
178 $this->assertSame($bar, $builder->get('bar'), '->get() returns the service associated with the id');
181 public function testRegisterDoesNotOverrideExistingService()
183 $builder = new ContainerBuilder();
184 $builder->set('bar', $bar = new \stdClass());
185 $builder->register('bar', 'stdClass');
187 $this->assertSame($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined');
190 public function testNonSharedServicesReturnsDifferentInstances()
192 $builder = new ContainerBuilder();
193 $builder->register('bar', 'stdClass')->setShared(false);
195 $this->assertNotSame($builder->get('bar'), $builder->get('bar'));
199 * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
200 * @expectedExceptionMessage You have requested a synthetic service ("foo"). The DIC does not know how to construct this service.
202 public function testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException()
204 $builder = new ContainerBuilder();
205 $builder->register('foo', 'stdClass')->setSynthetic(true);
207 // we expect a RuntimeException here as foo is synthetic
209 $builder->get('foo');
210 } catch (RuntimeException $e) {
213 // we must also have the same RuntimeException here
214 $builder->get('foo');
217 public function testGetServiceIds()
219 $builder = new ContainerBuilder();
220 $builder->register('foo', 'stdClass');
221 $builder->bar = $bar = new \stdClass();
222 $builder->register('bar', 'stdClass');
228 'Psr\Container\ContainerInterface',
229 'Symfony\Component\DependencyInjection\ContainerInterface',
231 $builder->getServiceIds(),
232 '->getServiceIds() returns all defined service ids'
236 public function testAliases()
238 $builder = new ContainerBuilder();
239 $builder->register('foo', 'stdClass');
240 $builder->setAlias('bar', 'foo');
241 $this->assertTrue($builder->hasAlias('bar'), '->hasAlias() returns true if the alias exists');
242 $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist');
243 $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service');
244 $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service');
245 $this->assertSame($builder->get('bar'), $builder->get('foo'), '->setAlias() creates a service that is an alias to another one');
248 $builder->setAlias('foobar', 'foobar');
249 $this->fail('->setAlias() throws an InvalidArgumentException if the alias references itself');
250 } catch (\InvalidArgumentException $e) {
251 $this->assertEquals('An alias can not reference itself, got a circular reference on "foobar".', $e->getMessage(), '->setAlias() throws an InvalidArgumentException if the alias references itself');
255 $builder->getAlias('foobar');
256 $this->fail('->getAlias() throws an InvalidArgumentException if the alias does not exist');
257 } catch (\InvalidArgumentException $e) {
258 $this->assertEquals('The service alias "foobar" does not exist.', $e->getMessage(), '->getAlias() throws an InvalidArgumentException if the alias does not exist');
262 public function testGetAliases()
264 $builder = new ContainerBuilder();
265 $builder->setAlias('bar', 'foo');
266 $builder->setAlias('foobar', 'foo');
267 $builder->setAlias('moo', new Alias('foo', false));
269 $aliases = $builder->getAliases();
270 $this->assertEquals('foo', (string) $aliases['bar']);
271 $this->assertTrue($aliases['bar']->isPublic());
272 $this->assertEquals('foo', (string) $aliases['foobar']);
273 $this->assertEquals('foo', (string) $aliases['moo']);
274 $this->assertFalse($aliases['moo']->isPublic());
276 $builder->register('bar', 'stdClass');
277 $this->assertFalse($builder->hasAlias('bar'));
279 $builder->set('foobar', 'stdClass');
280 $builder->set('moo', 'stdClass');
281 $this->assertCount(2, $builder->getAliases(), '->getAliases() does not return aliased services that have been overridden');
284 public function testSetAliases()
286 $builder = new ContainerBuilder();
287 $builder->setAliases(array('bar' => 'foo', 'foobar' => 'foo'));
289 $aliases = $builder->getAliases();
290 $this->assertArrayHasKey('bar', $aliases);
291 $this->assertArrayHasKey('foobar', $aliases);
294 public function testAddAliases()
296 $builder = new ContainerBuilder();
297 $builder->setAliases(array('bar' => 'foo'));
298 $builder->addAliases(array('foobar' => 'foo'));
300 $aliases = $builder->getAliases();
301 $this->assertArrayHasKey('bar', $aliases);
302 $this->assertArrayHasKey('foobar', $aliases);
305 public function testSetReplacesAlias()
307 $builder = new ContainerBuilder();
308 $builder->setAlias('alias', 'aliased');
309 $builder->set('aliased', new \stdClass());
311 $builder->set('alias', $foo = new \stdClass());
312 $this->assertSame($foo, $builder->get('alias'), '->set() replaces an existing alias');
315 public function testAliasesKeepInvalidBehavior()
317 $builder = new ContainerBuilder();
319 $aliased = new Definition('stdClass');
320 $aliased->addMethodCall('setBar', array(new Reference('bar', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)));
321 $builder->setDefinition('aliased', $aliased);
322 $builder->setAlias('alias', 'aliased');
324 $this->assertEquals(new \stdClass(), $builder->get('alias'));
327 public function testAddGetCompilerPass()
329 $builder = new ContainerBuilder();
330 $builder->setResourceTracking(false);
331 $defaultPasses = $builder->getCompiler()->getPassConfig()->getPasses();
332 $builder->addCompilerPass($pass1 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface')->getMock(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -5);
333 $builder->addCompilerPass($pass2 = $this->getMockBuilder('Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface')->getMock(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 10);
335 $passes = $builder->getCompiler()->getPassConfig()->getPasses();
336 $this->assertCount(count($passes) - 2, $defaultPasses);
337 // Pass 1 is executed later
338 $this->assertTrue(array_search($pass1, $passes, true) > array_search($pass2, $passes, true));
341 public function testCreateService()
343 $builder = new ContainerBuilder();
344 $builder->register('foo1', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
345 $builder->register('foo2', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php');
346 $builder->setParameter('file', 'foo');
347 $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition');
348 $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition');
351 public function testCreateProxyWithRealServiceInstantiator()
353 $builder = new ContainerBuilder();
355 $builder->register('foo1', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php');
356 $builder->getDefinition('foo1')->setLazy(true);
358 $foo1 = $builder->get('foo1');
360 $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls');
361 $this->assertSame('Bar\FooClass', get_class($foo1));
364 public function testCreateServiceClass()
366 $builder = new ContainerBuilder();
367 $builder->register('foo1', '%class%');
368 $builder->setParameter('class', 'stdClass');
369 $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition');
372 public function testCreateServiceArguments()
374 $builder = new ContainerBuilder();
375 $builder->register('bar', 'stdClass');
376 $builder->register('foo1', 'Bar\FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%'));
377 $builder->setParameter('value', 'bar');
378 $this->assertEquals(array('foo' => 'bar', 'bar' => 'foo', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->arguments, '->createService() replaces parameters and service references in the arguments provided by the service definition');
381 public function testCreateServiceFactory()
383 $builder = new ContainerBuilder();
384 $builder->register('foo', 'Bar\FooClass')->setFactory('Bar\FooClass::getInstance');
385 $builder->register('qux', 'Bar\FooClass')->setFactory(array('Bar\FooClass', 'getInstance'));
386 $builder->register('bar', 'Bar\FooClass')->setFactory(array(new Definition('Bar\FooClass'), 'getInstance'));
387 $builder->register('baz', 'Bar\FooClass')->setFactory(array(new Reference('bar'), 'getInstance'));
389 $this->assertTrue($builder->get('foo')->called, '->createService() calls the factory method to create the service instance');
390 $this->assertTrue($builder->get('qux')->called, '->createService() calls the factory method to create the service instance');
391 $this->assertTrue($builder->get('bar')->called, '->createService() uses anonymous service as factory');
392 $this->assertTrue($builder->get('baz')->called, '->createService() uses another service as factory');
395 public function testCreateServiceMethodCalls()
397 $builder = new ContainerBuilder();
398 $builder->register('bar', 'stdClass');
399 $builder->register('foo1', 'Bar\FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar'))));
400 $builder->setParameter('value', 'bar');
401 $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments');
404 public function testCreateServiceMethodCallsWithEscapedParam()
406 $builder = new ContainerBuilder();
407 $builder->register('bar', 'stdClass');
408 $builder->register('foo1', 'Bar\FooClass')->addMethodCall('setBar', array(array('%%unescape_it%%')));
409 $builder->setParameter('value', 'bar');
410 $this->assertEquals(array('%unescape_it%'), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments');
413 public function testCreateServiceProperties()
415 $builder = new ContainerBuilder();
416 $builder->register('bar', 'stdClass');
417 $builder->register('foo1', 'Bar\FooClass')->setProperty('bar', array('%value%', new Reference('bar'), '%%unescape_it%%'));
418 $builder->setParameter('value', 'bar');
419 $this->assertEquals(array('bar', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->bar, '->createService() replaces the values in the properties');
422 public function testCreateServiceConfigurator()
424 $builder = new ContainerBuilder();
425 $builder->register('foo1', 'Bar\FooClass')->setConfigurator('sc_configure');
426 $builder->register('foo2', 'Bar\FooClass')->setConfigurator(array('%class%', 'configureStatic'));
427 $builder->setParameter('class', 'BazClass');
428 $builder->register('baz', 'BazClass');
429 $builder->register('foo3', 'Bar\FooClass')->setConfigurator(array(new Reference('baz'), 'configure'));
430 $builder->register('foo4', 'Bar\FooClass')->setConfigurator(array($builder->getDefinition('baz'), 'configure'));
431 $builder->register('foo5', 'Bar\FooClass')->setConfigurator('foo');
433 $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator');
434 $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator');
435 $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator');
436 $this->assertTrue($builder->get('foo4')->configured, '->createService() calls the configurator');
439 $builder->get('foo5');
440 $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
441 } catch (\InvalidArgumentException $e) {
442 $this->assertEquals('The configure callable for class "Bar\FooClass" is not a callable.', $e->getMessage(), '->createService() throws an InvalidArgumentException if the configure callable is not a valid callable');
446 public function testCreateServiceWithIteratorArgument()
448 $builder = new ContainerBuilder();
449 $builder->register('bar', 'stdClass');
451 ->register('lazy_context', 'LazyContext')
452 ->setArguments(array(
453 new IteratorArgument(array('k1' => new Reference('bar'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))),
454 new IteratorArgument(array()),
458 $lazyContext = $builder->get('lazy_context');
459 $this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyValues);
460 $this->assertInstanceOf(RewindableGenerator::class, $lazyContext->lazyEmptyValues);
461 $this->assertCount(1, $lazyContext->lazyValues);
462 $this->assertCount(0, $lazyContext->lazyEmptyValues);
465 foreach ($lazyContext->lazyValues as $k => $v) {
467 $this->assertEquals('k1', $k);
468 $this->assertInstanceOf('\stdClass', $v);
471 // The second argument should have been ignored.
472 $this->assertEquals(1, $i);
475 foreach ($lazyContext->lazyEmptyValues as $k => $v) {
479 $this->assertEquals(0, $i);
483 * @expectedException \RuntimeException
485 public function testCreateSyntheticService()
487 $builder = new ContainerBuilder();
488 $builder->register('foo', 'Bar\FooClass')->setSynthetic(true);
489 $builder->get('foo');
492 public function testCreateServiceWithExpression()
494 $builder = new ContainerBuilder();
495 $builder->setParameter('bar', 'bar');
496 $builder->register('bar', 'BarClass');
497 $builder->register('foo', 'Bar\FooClass')->addArgument(array('foo' => new Expression('service("bar").foo ~ parameter("bar")')));
498 $this->assertEquals('foobar', $builder->get('foo')->arguments['foo']);
501 public function testResolveServices()
503 $builder = new ContainerBuilder();
504 $builder->register('foo', 'Bar\FooClass');
505 $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances');
506 $this->assertEquals(array('foo' => array('foo', $builder->get('foo'))), $builder->resolveServices(array('foo' => array('foo', new Reference('foo')))), '->resolveServices() resolves service references to service instances in nested arrays');
507 $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions');
511 * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
512 * @expectedExceptionMessage Constructing service "foo" from a parent definition is not supported at build time.
514 public function testResolveServicesWithDecoratedDefinition()
516 $builder = new ContainerBuilder();
517 $builder->setDefinition('grandpa', new Definition('stdClass'));
518 $builder->setDefinition('parent', new ChildDefinition('grandpa'));
519 $builder->setDefinition('foo', new ChildDefinition('parent'));
521 $builder->get('foo');
524 public function testResolveServicesWithCustomDefinitionClass()
526 $builder = new ContainerBuilder();
527 $builder->setDefinition('foo', new CustomDefinition('stdClass'));
529 $this->assertInstanceOf('stdClass', $builder->get('foo'));
532 public function testMerge()
534 $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
535 $container->setResourceTracking(false);
536 $config = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
537 $container->merge($config);
538 $this->assertEquals(array('bar' => 'foo', 'foo' => 'bar'), $container->getParameterBag()->all(), '->merge() merges current parameters with the loaded ones');
540 $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
541 $container->setResourceTracking(false);
542 $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%')));
543 $container->merge($config);
544 $container->compile();
545 $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');
547 $container = new ContainerBuilder(new ParameterBag(array('bar' => 'foo')));
548 $container->setResourceTracking(false);
549 $config = new ContainerBuilder(new ParameterBag(array('foo' => '%bar%', 'baz' => '%foo%')));
550 $container->merge($config);
551 $container->compile();
552 $this->assertEquals(array('bar' => 'foo', 'foo' => 'foo', 'baz' => 'foo'), $container->getParameterBag()->all(), '->merge() evaluates the values of the parameters towards already defined ones');
554 $container = new ContainerBuilder();
555 $container->setResourceTracking(false);
556 $container->register('foo', 'Bar\FooClass');
557 $container->register('bar', 'BarClass');
558 $config = new ContainerBuilder();
559 $config->setDefinition('baz', new Definition('BazClass'));
560 $config->setAlias('alias_for_foo', 'foo');
561 $container->merge($config);
562 $this->assertEquals(array('service_container', 'foo', 'bar', 'baz'), array_keys($container->getDefinitions()), '->merge() merges definitions already defined ones');
564 $aliases = $container->getAliases();
565 $this->assertArrayHasKey('alias_for_foo', $aliases);
566 $this->assertEquals('foo', (string) $aliases['alias_for_foo']);
568 $container = new ContainerBuilder();
569 $container->setResourceTracking(false);
570 $container->register('foo', 'Bar\FooClass');
571 $config->setDefinition('foo', new Definition('BazClass'));
572 $container->merge($config);
573 $this->assertEquals('BazClass', $container->getDefinition('foo')->getClass(), '->merge() overrides already defined services');
575 $container = new ContainerBuilder();
576 $bag = new EnvPlaceholderParameterBag();
577 $bag->get('env(Foo)');
578 $config = new ContainerBuilder($bag);
579 $this->assertSame(array('%env(Bar)%'), $config->resolveEnvPlaceholders(array($bag->get('env(Bar)'))));
580 $container->merge($config);
581 $this->assertEquals(array('Foo' => 0, 'Bar' => 1), $container->getEnvCounters());
583 $container = new ContainerBuilder();
584 $config = new ContainerBuilder();
585 $childDefA = $container->registerForAutoconfiguration('AInterface');
586 $childDefB = $config->registerForAutoconfiguration('BInterface');
587 $container->merge($config);
588 $this->assertSame(array('AInterface' => $childDefA, 'BInterface' => $childDefB), $container->getAutoconfiguredInstanceof());
592 * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
593 * @expectedExceptionMessage "AInterface" has already been autoconfigured and merge() does not support merging autoconfiguration for the same class/interface.
595 public function testMergeThrowsExceptionForDuplicateAutomaticInstanceofDefinitions()
597 $container = new ContainerBuilder();
598 $config = new ContainerBuilder();
599 $container->registerForAutoconfiguration('AInterface');
600 $config->registerForAutoconfiguration('AInterface');
601 $container->merge($config);
604 public function testResolveEnvValues()
606 $_ENV['DUMMY_ENV_VAR'] = 'du%%y';
607 $_SERVER['DUMMY_SERVER_VAR'] = 'ABC';
608 $_SERVER['HTTP_DUMMY_VAR'] = 'DEF';
610 $container = new ContainerBuilder();
611 $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%');
612 $container->setParameter('env(HTTP_DUMMY_VAR)', '123');
614 $this->assertSame('%% du%%%%y ABC 123', $container->resolveEnvPlaceholders('%bar%', true));
616 unset($_ENV['DUMMY_ENV_VAR'], $_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']);
619 public function testResolveEnvValuesWithArray()
621 $_ENV['ANOTHER_DUMMY_ENV_VAR'] = 'dummy';
623 $dummyArray = array('1' => 'one', '2' => 'two');
625 $container = new ContainerBuilder();
626 $container->setParameter('dummy', '%env(ANOTHER_DUMMY_ENV_VAR)%');
627 $container->setParameter('dummy2', $dummyArray);
629 $container->resolveEnvPlaceholders('%dummy%', true);
630 $container->resolveEnvPlaceholders('%dummy2%', true);
632 $this->assertInternalType('array', $container->resolveEnvPlaceholders('%dummy2%', true));
634 foreach ($dummyArray as $key => $value) {
635 $this->assertArrayHasKey($key, $container->resolveEnvPlaceholders('%dummy2%', true));
638 unset($_ENV['ANOTHER_DUMMY_ENV_VAR']);
641 public function testCompileWithResolveEnv()
643 putenv('DUMMY_ENV_VAR=du%%y');
644 $_SERVER['DUMMY_SERVER_VAR'] = 'ABC';
645 $_SERVER['HTTP_DUMMY_VAR'] = 'DEF';
647 $container = new ContainerBuilder();
648 $container->setParameter('env(FOO)', 'Foo');
649 $container->setParameter('env(DUMMY_ENV_VAR)', 'GHI');
650 $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%');
651 $container->setParameter('foo', '%env(FOO)%');
652 $container->setParameter('baz', '%foo%');
653 $container->setParameter('env(HTTP_DUMMY_VAR)', '123');
654 $container->register('teatime', 'stdClass')
655 ->setProperty('foo', '%env(DUMMY_ENV_VAR)%')
658 $container->compile(true);
660 $this->assertSame('% du%%y ABC 123', $container->getParameter('bar'));
661 $this->assertSame('Foo', $container->getParameter('baz'));
662 $this->assertSame('du%%y', $container->get('teatime')->foo);
664 unset($_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']);
665 putenv('DUMMY_ENV_VAR');
668 public function testCompileWithArrayResolveEnv()
670 putenv('ARRAY={"foo":"bar"}');
672 $container = new ContainerBuilder();
673 $container->setParameter('foo', '%env(json:ARRAY)%');
674 $container->compile(true);
676 $this->assertSame(array('foo' => 'bar'), $container->getParameter('foo'));
681 public function testCompileWithArrayAndAnotherResolveEnv()
683 putenv('DUMMY_ENV_VAR=abc');
684 putenv('ARRAY={"foo":"bar"}');
686 $container = new ContainerBuilder();
687 $container->setParameter('foo', '%env(json:ARRAY)%');
688 $container->setParameter('bar', '%env(DUMMY_ENV_VAR)%');
689 $container->compile(true);
691 $this->assertSame(array('foo' => 'bar'), $container->getParameter('foo'));
692 $this->assertSame('abc', $container->getParameter('bar'));
694 putenv('DUMMY_ENV_VAR');
699 * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
700 * @expectedExceptionMessage A string value must be composed of strings and/or numbers, but found parameter "env(json:ARRAY)" of type array inside string value "ABC %env(json:ARRAY)%".
702 public function testCompileWithArrayInStringResolveEnv()
704 putenv('ARRAY={"foo":"bar"}');
706 $container = new ContainerBuilder();
707 $container->setParameter('foo', 'ABC %env(json:ARRAY)%');
708 $container->compile(true);
714 * @expectedException \Symfony\Component\DependencyInjection\Exception\EnvNotFoundException
715 * @expectedExceptionMessage Environment variable not found: "FOO".
717 public function testCompileWithResolveMissingEnv()
719 $container = new ContainerBuilder();
720 $container->setParameter('foo', '%env(FOO)%');
721 $container->compile(true);
724 public function testDynamicEnv()
726 putenv('DUMMY_FOO=some%foo%');
727 putenv('DUMMY_BAR=%bar%');
729 $container = new ContainerBuilder();
730 $container->setParameter('foo', 'Foo%env(resolve:DUMMY_BAR)%');
731 $container->setParameter('bar', 'Bar');
732 $container->setParameter('baz', '%env(resolve:DUMMY_FOO)%');
734 $container->compile(true);
738 $this->assertSame('someFooBar', $container->getParameter('baz'));
741 public function testCastEnv()
743 $container = new ContainerBuilder();
744 $container->setParameter('env(FAKE)', '123');
746 $container->register('foo', 'stdClass')
748 ->setProperties(array(
749 'fake' => '%env(int:FAKE)%',
752 $container->compile(true);
754 $this->assertSame(123, $container->get('foo')->fake);
757 public function testEnvAreNullable()
759 $container = new ContainerBuilder();
760 $container->setParameter('env(FAKE)', null);
762 $container->register('foo', 'stdClass')
764 ->setProperties(array(
765 'fake' => '%env(int:FAKE)%',
768 $container->compile(true);
770 $this->assertNull($container->get('foo')->fake);
773 public function testEnvInId()
775 $container = include __DIR__.'/Fixtures/containers/container_env_in_id.php';
776 $container->compile(true);
784 $this->assertSame($expected, array_keys($container->getDefinitions()));
787 PsrContainerInterface::class => true,
788 ContainerInterface::class => true,
789 'baz_%env(BAR)%' => true,
790 'bar_%env(BAR)%' => true,
792 $this->assertSame($expected, $container->getRemovedIds());
794 $this->assertSame(array('baz_bar'), array_keys($container->getDefinition('foo')->getArgument(1)));
798 * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException
799 * @expectedExceptionMessage Circular reference detected for parameter "env(resolve:DUMMY_ENV_VAR)" ("env(resolve:DUMMY_ENV_VAR)" > "env(resolve:DUMMY_ENV_VAR)").
801 public function testCircularDynamicEnv()
803 putenv('DUMMY_ENV_VAR=some%foo%');
805 $container = new ContainerBuilder();
806 $container->setParameter('foo', '%bar%');
807 $container->setParameter('bar', '%env(resolve:DUMMY_ENV_VAR)%');
810 $container->compile(true);
812 putenv('DUMMY_ENV_VAR');
817 * @expectedException \LogicException
819 public function testMergeLogicException()
821 $container = new ContainerBuilder();
822 $container->setResourceTracking(false);
823 $container->compile();
824 $container->merge(new ContainerBuilder());
827 public function testfindTaggedServiceIds()
829 $builder = new ContainerBuilder();
831 ->register('foo', 'Bar\FooClass')
832 ->addTag('foo', array('foo' => 'foo'))
833 ->addTag('bar', array('bar' => 'bar'))
834 ->addTag('foo', array('foofoo' => 'foofoo'))
836 $this->assertEquals($builder->findTaggedServiceIds('foo'), array(
838 array('foo' => 'foo'),
839 array('foofoo' => 'foofoo'),
841 ), '->findTaggedServiceIds() returns an array of service ids and its tag attributes');
842 $this->assertEquals(array(), $builder->findTaggedServiceIds('foobar'), '->findTaggedServiceIds() returns an empty array if there is annotated services');
845 public function testFindUnusedTags()
847 $builder = new ContainerBuilder();
849 ->register('foo', 'Bar\FooClass')
850 ->addTag('kernel.event_listener', array('foo' => 'foo'))
851 ->addTag('kenrel.event_listener', array('bar' => 'bar'))
853 $builder->findTaggedServiceIds('kernel.event_listener');
854 $this->assertEquals(array('kenrel.event_listener'), $builder->findUnusedTags(), '->findUnusedTags() returns an array with unused tags');
857 public function testFindDefinition()
859 $container = new ContainerBuilder();
860 $container->setDefinition('foo', $definition = new Definition('Bar\FooClass'));
861 $container->setAlias('bar', 'foo');
862 $container->setAlias('foobar', 'bar');
863 $this->assertEquals($definition, $container->findDefinition('foobar'), '->findDefinition() returns a Definition');
866 public function testAddObjectResource()
868 $container = new ContainerBuilder();
870 $container->setResourceTracking(false);
871 $container->addObjectResource(new \BarClass());
873 $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
875 $container->setResourceTracking(true);
876 $container->addObjectResource(new \BarClass());
878 $resources = $container->getResources();
880 $this->assertCount(2, $resources, '2 resources were registered');
882 /* @var $resource \Symfony\Component\Config\Resource\FileResource */
883 $resource = end($resources);
885 $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
886 $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
892 public function testAddClassResource()
894 $container = new ContainerBuilder();
896 $container->setResourceTracking(false);
897 $container->addClassResource(new \ReflectionClass('BarClass'));
899 $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
901 $container->setResourceTracking(true);
902 $container->addClassResource(new \ReflectionClass('BarClass'));
904 $resources = $container->getResources();
906 $this->assertCount(2, $resources, '2 resources were registered');
908 /* @var $resource \Symfony\Component\Config\Resource\FileResource */
909 $resource = end($resources);
911 $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource);
912 $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource()));
915 public function testGetReflectionClass()
917 $container = new ContainerBuilder();
919 $container->setResourceTracking(false);
920 $r1 = $container->getReflectionClass('BarClass');
922 $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
924 $container->setResourceTracking(true);
925 $r2 = $container->getReflectionClass('BarClass');
926 $r3 = $container->getReflectionClass('BarClass');
928 $this->assertNull($container->getReflectionClass('BarMissingClass'));
930 $this->assertEquals($r1, $r2);
931 $this->assertSame($r2, $r3);
933 $resources = $container->getResources();
935 $this->assertCount(3, $resources, '3 resources were registered');
937 $this->assertSame('reflection.BarClass', (string) $resources[1]);
938 $this->assertSame('BarMissingClass', (string) end($resources));
941 public function testGetReflectionClassOnInternalTypes()
943 $container = new ContainerBuilder();
945 $this->assertNull($container->getReflectionClass('int'));
946 $this->assertNull($container->getReflectionClass('float'));
947 $this->assertNull($container->getReflectionClass('string'));
948 $this->assertNull($container->getReflectionClass('bool'));
949 $this->assertNull($container->getReflectionClass('resource'));
950 $this->assertNull($container->getReflectionClass('object'));
951 $this->assertNull($container->getReflectionClass('array'));
952 $this->assertNull($container->getReflectionClass('null'));
953 $this->assertNull($container->getReflectionClass('callable'));
954 $this->assertNull($container->getReflectionClass('iterable'));
955 $this->assertNull($container->getReflectionClass('mixed'));
958 public function testCompilesClassDefinitionsOfLazyServices()
960 $container = new ContainerBuilder();
962 $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking');
964 $container->register('foo', 'BarClass')->setPublic(true);
965 $container->getDefinition('foo')->setLazy(true);
967 $container->compile();
969 $matchingResources = array_filter(
970 $container->getResources(),
971 function (ResourceInterface $resource) {
972 return 'reflection.BarClass' === (string) $resource;
976 $this->assertNotEmpty($matchingResources);
979 public function testResources()
981 $container = new ContainerBuilder();
982 $container->addResource($a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml'));
983 $container->addResource($b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml'));
984 $resources = array();
985 foreach ($container->getResources() as $resource) {
986 if (false === strpos($resource, '.php')) {
987 $resources[] = $resource;
990 $this->assertEquals(array($a, $b), $resources, '->getResources() returns an array of resources read for the current configuration');
991 $this->assertSame($container, $container->setResources(array()));
992 $this->assertEquals(array(), $container->getResources());
995 public function testFileExists()
997 $container = new ContainerBuilder();
998 $A = new ComposerResource();
999 $a = new FileResource(__DIR__.'/Fixtures/xml/services1.xml');
1000 $b = new FileResource(__DIR__.'/Fixtures/xml/services2.xml');
1001 $c = new DirectoryResource($dir = dirname($b));
1003 $this->assertTrue($container->fileExists((string) $a) && $container->fileExists((string) $b) && $container->fileExists($dir));
1005 $resources = array();
1006 foreach ($container->getResources() as $resource) {
1007 if (false === strpos($resource, '.php')) {
1008 $resources[] = $resource;
1012 $this->assertEquals(array($A, $a, $b, $c), $resources, '->getResources() returns an array of resources read for the current configuration');
1015 public function testExtension()
1017 $container = new ContainerBuilder();
1018 $container->setResourceTracking(false);
1020 $container->registerExtension($extension = new \ProjectExtension());
1021 $this->assertSame($container->getExtension('project'), $extension, '->registerExtension() registers an extension');
1023 $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('LogicException');
1024 $container->getExtension('no_registered');
1027 public function testRegisteredButNotLoadedExtension()
1029 $extension = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface')->getMock();
1030 $extension->expects($this->once())->method('getAlias')->will($this->returnValue('project'));
1031 $extension->expects($this->never())->method('load');
1033 $container = new ContainerBuilder();
1034 $container->setResourceTracking(false);
1035 $container->registerExtension($extension);
1036 $container->compile();
1039 public function testRegisteredAndLoadedExtension()
1041 $extension = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\Extension\\ExtensionInterface')->getMock();
1042 $extension->expects($this->exactly(2))->method('getAlias')->will($this->returnValue('project'));
1043 $extension->expects($this->once())->method('load')->with(array(array('foo' => 'bar')));
1045 $container = new ContainerBuilder();
1046 $container->setResourceTracking(false);
1047 $container->registerExtension($extension);
1048 $container->loadFromExtension('project', array('foo' => 'bar'));
1049 $container->compile();
1052 public function testPrivateServiceUser()
1054 $fooDefinition = new Definition('BarClass');
1055 $fooUserDefinition = new Definition('BarUserClass', array(new Reference('bar')));
1056 $container = new ContainerBuilder();
1057 $container->setResourceTracking(false);
1059 $fooDefinition->setPublic(false);
1061 $container->addDefinitions(array(
1062 'bar' => $fooDefinition,
1063 'bar_user' => $fooUserDefinition->setPublic(true),
1066 $container->compile();
1067 $this->assertInstanceOf('BarClass', $container->get('bar_user')->bar);
1071 * @expectedException \BadMethodCallException
1073 public function testThrowsExceptionWhenSetServiceOnACompiledContainer()
1075 $container = new ContainerBuilder();
1076 $container->setResourceTracking(false);
1077 $container->register('a', 'stdClass')->setPublic(true);
1078 $container->compile();
1079 $container->set('a', new \stdClass());
1082 public function testThrowsExceptionWhenAddServiceOnACompiledContainer()
1084 $container = new ContainerBuilder();
1085 $container->compile();
1086 $container->set('a', $foo = new \stdClass());
1087 $this->assertSame($foo, $container->get('a'));
1090 public function testNoExceptionWhenSetSyntheticServiceOnACompiledContainer()
1092 $container = new ContainerBuilder();
1093 $def = new Definition('stdClass');
1094 $def->setSynthetic(true)->setPublic(true);
1095 $container->setDefinition('a', $def);
1096 $container->compile();
1097 $container->set('a', $a = new \stdClass());
1098 $this->assertEquals($a, $container->get('a'));
1102 * @expectedException \BadMethodCallException
1104 public function testThrowsExceptionWhenSetDefinitionOnACompiledContainer()
1106 $container = new ContainerBuilder();
1107 $container->setResourceTracking(false);
1108 $container->compile();
1109 $container->setDefinition('a', new Definition());
1112 public function testExtensionConfig()
1114 $container = new ContainerBuilder();
1116 $configs = $container->getExtensionConfig('foo');
1117 $this->assertEmpty($configs);
1119 $first = array('foo' => 'bar');
1120 $container->prependExtensionConfig('foo', $first);
1121 $configs = $container->getExtensionConfig('foo');
1122 $this->assertEquals(array($first), $configs);
1124 $second = array('ding' => 'dong');
1125 $container->prependExtensionConfig('foo', $second);
1126 $configs = $container->getExtensionConfig('foo');
1127 $this->assertEquals(array($second, $first), $configs);
1130 public function testAbstractAlias()
1132 $container = new ContainerBuilder();
1134 $abstract = new Definition('AbstractClass');
1135 $abstract->setAbstract(true)->setPublic(true);
1137 $container->setDefinition('abstract_service', $abstract);
1138 $container->setAlias('abstract_alias', 'abstract_service')->setPublic(true);
1140 $container->compile();
1142 $this->assertSame('abstract_service', (string) $container->getAlias('abstract_alias'));
1145 public function testLazyLoadedService()
1147 $loader = new ClosureLoader($container = new ContainerBuilder());
1148 $loader->load(function (ContainerBuilder $container) {
1149 $container->set('a', new \BazClass());
1150 $definition = new Definition('BazClass');
1151 $definition->setLazy(true);
1152 $definition->setPublic(true);
1153 $container->setDefinition('a', $definition);
1156 $container->setResourceTracking(true);
1158 $container->compile();
1160 $r = new \ReflectionProperty($container, 'resources');
1161 $r->setAccessible(true);
1162 $resources = $r->getValue($container);
1164 $classInList = false;
1165 foreach ($resources as $resource) {
1166 if ('reflection.BazClass' === (string) $resource) {
1167 $classInList = true;
1172 $this->assertTrue($classInList);
1175 public function testInlinedDefinitions()
1177 $container = new ContainerBuilder();
1179 $definition = new Definition('BarClass');
1181 $container->register('bar_user', 'BarUserClass')
1182 ->addArgument($definition)
1183 ->setProperty('foo', $definition);
1185 $container->register('bar', 'BarClass')
1186 ->setProperty('foo', $definition)
1187 ->addMethodCall('setBaz', array($definition));
1189 $barUser = $container->get('bar_user');
1190 $bar = $container->get('bar');
1192 $this->assertSame($barUser->foo, $barUser->bar);
1193 $this->assertSame($bar->foo, $bar->getBaz());
1194 $this->assertNotSame($bar->foo, $barUser->foo);
1198 * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
1199 * @expectedExceptionMessage Circular reference detected for service "app.test_class", path: "app.test_class -> App\TestClass -> app.test_class".
1201 public function testThrowsCircularExceptionForCircularAliases()
1203 $builder = new ContainerBuilder();
1205 $builder->setAliases(array(
1206 'foo' => new Alias('app.test_class'),
1207 'app.test_class' => new Alias('App\\TestClass'),
1208 'App\\TestClass' => new Alias('app.test_class'),
1211 $builder->findDefinition('foo');
1214 public function testInitializePropertiesBeforeMethodCalls()
1216 $container = new ContainerBuilder();
1217 $container->register('foo', 'stdClass');
1218 $container->register('bar', 'MethodCallClass')
1220 ->setProperty('simple', 'bar')
1221 ->setProperty('complex', new Reference('foo'))
1222 ->addMethodCall('callMe');
1224 $container->compile();
1226 $this->assertTrue($container->get('bar')->callPassed(), '->compile() initializes properties before method calls');
1229 public function testAutowiring()
1231 $container = new ContainerBuilder();
1233 $container->register(A::class)->setPublic(true);
1234 $bDefinition = $container->register('b', __NAMESPACE__.'\B');
1235 $bDefinition->setAutowired(true);
1236 $bDefinition->setPublic(true);
1238 $container->compile();
1240 $this->assertEquals(A::class, (string) $container->getDefinition('b')->getArgument(0));
1243 public function testClassFromId()
1245 $container = new ContainerBuilder();
1247 $unknown = $container->register('Acme\UnknownClass');
1248 $autoloadClass = $container->register(CaseSensitiveClass::class);
1249 $container->compile();
1251 $this->assertSame('Acme\UnknownClass', $unknown->getClass());
1252 $this->assertEquals(CaseSensitiveClass::class, $autoloadClass->getClass());
1256 * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
1257 * @expectedExceptionMessage The definition for "DateTime" has no class attribute, and appears to reference a class or interface in the global namespace.
1259 public function testNoClassFromGlobalNamespaceClassId()
1261 $container = new ContainerBuilder();
1263 $definition = $container->register(\DateTime::class);
1264 $container->compile();
1268 * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
1269 * @expectedExceptionMessage The definition for "123_abc" has no class.
1271 public function testNoClassFromNonClassId()
1273 $container = new ContainerBuilder();
1275 $definition = $container->register('123_abc');
1276 $container->compile();
1280 * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
1281 * @expectedExceptionMessage The definition for "\foo" has no class.
1283 public function testNoClassFromNsSeparatorId()
1285 $container = new ContainerBuilder();
1287 $definition = $container->register('\\foo');
1288 $container->compile();
1291 public function testServiceLocator()
1293 $container = new ContainerBuilder();
1294 $container->register('foo_service', ServiceLocator::class)
1296 ->addArgument(array(
1297 'bar' => new ServiceClosureArgument(new Reference('bar_service')),
1298 'baz' => new ServiceClosureArgument(new TypedReference('baz_service', 'stdClass')),
1301 $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true);
1302 $container->register('baz_service', 'stdClass')->setPublic(false);
1303 $container->compile();
1305 $this->assertInstanceOf(ServiceLocator::class, $foo = $container->get('foo_service'));
1306 $this->assertSame($container->get('bar_service'), $foo->get('bar'));
1309 public function testUninitializedReference()
1311 $container = include __DIR__.'/Fixtures/containers/container_uninitialized_ref.php';
1312 $container->compile();
1314 $bar = $container->get('bar');
1316 $this->assertNull($bar->foo1);
1317 $this->assertNull($bar->foo2);
1318 $this->assertNull($bar->foo3);
1319 $this->assertNull($bar->closures[0]());
1320 $this->assertNull($bar->closures[1]());
1321 $this->assertNull($bar->closures[2]());
1322 $this->assertSame(array(), iterator_to_array($bar->iter));
1324 $container = include __DIR__.'/Fixtures/containers/container_uninitialized_ref.php';
1325 $container->compile();
1327 $container->get('foo1');
1328 $container->get('baz');
1330 $bar = $container->get('bar');
1332 $this->assertEquals(new \stdClass(), $bar->foo1);
1333 $this->assertNull($bar->foo2);
1334 $this->assertEquals(new \stdClass(), $bar->foo3);
1335 $this->assertEquals(new \stdClass(), $bar->closures[0]());
1336 $this->assertNull($bar->closures[1]());
1337 $this->assertEquals(new \stdClass(), $bar->closures[2]());
1338 $this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter));
1342 * @dataProvider provideAlmostCircular
1344 public function testAlmostCircular($visibility)
1346 $container = include __DIR__.'/Fixtures/containers/container_almost_circular.php';
1348 $foo = $container->get('foo');
1349 $this->assertSame($foo, $foo->bar->foobar->foo);
1351 $foo2 = $container->get('foo2');
1352 $this->assertSame($foo2, $foo2->bar->foobar->foo);
1354 $this->assertSame(array(), (array) $container->get('foobar4'));
1356 $foo5 = $container->get('foo5');
1357 $this->assertSame($foo5, $foo5->bar->foo);
1360 public function provideAlmostCircular()
1362 yield array('public');
1363 yield array('private');
1366 public function testRegisterForAutoconfiguration()
1368 $container = new ContainerBuilder();
1369 $childDefA = $container->registerForAutoconfiguration('AInterface');
1370 $childDefB = $container->registerForAutoconfiguration('BInterface');
1371 $this->assertSame(array('AInterface' => $childDefA, 'BInterface' => $childDefB), $container->getAutoconfiguredInstanceof());
1373 // when called multiple times, the same instance is returned
1374 $this->assertSame($childDefA, $container->registerForAutoconfiguration('AInterface'));
1378 * This test checks the trigger of a deprecation note and should not be removed in major releases.
1381 * @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will soon be removed.
1383 public function testPrivateServiceTriggersDeprecation()
1385 $container = new ContainerBuilder();
1386 $container->register('foo', 'stdClass')
1388 ->setDeprecated(true);
1389 $container->register('bar', 'stdClass')
1391 ->setProperty('foo', new Reference('foo'));
1393 $container->compile();
1395 $container->get('bar');
1400 * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since Symfony 3.4.
1402 public function testParameterWithMixedCase()
1404 $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar')));
1405 $container->register('foo', 'stdClass')
1407 ->setProperty('foo', '%FOO%');
1409 $container->compile();
1411 $this->assertSame('bar', $container->get('foo')->foo);
1414 public function testArgumentsHaveHigherPriorityThanBindings()
1416 $container = new ContainerBuilder();
1417 $container->register('class.via.bindings', CaseSensitiveClass::class)->setArguments(array(
1420 $container->register('class.via.argument', CaseSensitiveClass::class)->setArguments(array(
1423 $container->register('foo', SimilarArgumentsDummy::class)->setPublic(true)->setBindings(array(
1424 CaseSensitiveClass::class => new Reference('class.via.bindings'),
1426 ))->setArguments(array(
1427 '$class1' => new Reference('class.via.argument'),
1430 $this->assertSame(array('service_container', 'class.via.bindings', 'class.via.argument', 'foo', 'Psr\Container\ContainerInterface', 'Symfony\Component\DependencyInjection\ContainerInterface'), $container->getServiceIds());
1432 $container->compile();
1434 $this->assertSame('via-argument', $container->get('foo')->class1->identifier);
1435 $this->assertSame('via-bindings', $container->get('foo')->class2->identifier);
1449 public function __construct(A $a)