diff --git a/UPGRADE-3.2.md b/UPGRADE-3.2.md new file mode 100644 index 0000000000000..634f284cc240e --- /dev/null +++ b/UPGRADE-3.2.md @@ -0,0 +1,8 @@ +UPGRADE FROM 3.1 to 3.2 +======================= + +DependencyInjection +------------------- + + * Calling `get()` on a `ContainerBuilder` instance before compiling the + container is deprecated and will throw an exception in Symfony 4.0. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 1f5a00bbf9306..f2d08335953e3 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -4,6 +4,9 @@ UPGRADE FROM 3.x to 4.0 DependencyInjection ------------------- + * Calling `get()` on a `ContainerBuilder` instance before compiling the + container is not supported anymore and will throw an exception. + * Using unsupported configuration keys in YAML configuration files raises an exception. diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php index ae13d543b0e1e..3f3c577b846df 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php @@ -33,6 +33,8 @@ public function testCreateProxyServiceWithRuntimeInstantiator() $builder->register('foo1', 'ProxyManagerBridgeFooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); $builder->getDefinition('foo1')->setLazy(true); + $builder->compile(); + /* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ $foo1 = $builder->get('foo1'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php index dde5c1439f202..da809aea8df63 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php @@ -256,6 +256,10 @@ protected function resolveServiceDefinition(ContainerBuilder $builder, $serviceI return $builder->getAlias($serviceId); } + if ('service_container' === $serviceId) { + return $builder; + } + // the service has been injected in some special way, just return the service return $builder->get($serviceId); } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index a3732fde425b1..f4424d0cc7d5c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -96,11 +96,11 @@ public function testToolbarConfig($toolbarEnabled, $interceptRedirects, $listene $this->assertSame($listenerInjected, $this->container->has('web_profiler.debug_toolbar')); + $this->assertSaneContainer($this->getDumpedContainer()); + if ($listenerInjected) { $this->assertSame($listenerEnabled, $this->container->get('web_profiler.debug_toolbar')->isEnabled()); } - - $this->assertSaneContainer($this->getDumpedContainer()); } public function getDebugModes() diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index aae5460ace603..7a9703432b77c 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -94,6 +94,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface */ private $usedTags = array(); + private $compiled = false; + /** * Sets the track resources flag. * @@ -409,6 +411,10 @@ public function has($id) */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { + if (!$this->compiled) { + @trigger_error(sprintf('Calling %s() before compiling the container is deprecated since version 3.2 and will throw an exception in 4.0.', __METHOD__), E_USER_DEPRECATED); + } + $id = strtolower($id); if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { @@ -543,6 +549,7 @@ public function compile() } $compiler->compile($this); + $this->compiled = true; if ($this->trackResources) { foreach ($this->definitions as $definition) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php index 376487d3ab9f3..c569232f20f1d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php @@ -180,14 +180,17 @@ private function findNodes() } foreach ($container->getServiceIds() as $id) { - $service = $container->get($id); - if (array_key_exists($id, $container->getAliases())) { continue; } if (!$container->hasDefinition($id)) { - $class = ('service_container' === $id) ? get_class($this->container) : get_class($service); + if ('service_container' === $id) { + $class = get_class($this->container); + } else { + $class = get_class($container->get($id)); + } + $nodes[$id] = array('class' => str_replace('\\', '\\\\', $class), 'attributes' => $this->options['node.instance']); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php index e3aba6d7074cd..a8d32815e7128 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php @@ -57,7 +57,6 @@ public function testProcessWithNonExistingAlias() $pass->process($container); $this->assertEquals('Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassDefault', $container->getDefinition('example')->getClass()); - $this->assertInstanceOf('Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassDefault', $container->get('example')); } public function testProcessWithExistingAlias() @@ -75,7 +74,7 @@ public function testProcessWithExistingAlias() $this->assertTrue($container->hasAlias('example')); $this->assertEquals('mysql.example', $container->getAlias('example')); - $this->assertInstanceOf('Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMysql', $container->get('example')); + $this->assertSame('Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMysql', $container->getDefinition('mysql.example')->getClass()); } public function testProcessWithManualAlias() @@ -86,7 +85,7 @@ public function testProcessWithManualAlias() ->addTag('auto_alias', array('format' => '%existing%.example')); $container->register('mysql.example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMysql'); - $container->register('mariadb.example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMariadb'); + $container->register('mariadb.example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMariaDb'); $container->setAlias('example', 'mariadb.example'); $container->setParameter('existing', 'mysql'); @@ -95,7 +94,7 @@ public function testProcessWithManualAlias() $this->assertTrue($container->hasAlias('example')); $this->assertEquals('mariadb.example', $container->getAlias('example')); - $this->assertInstanceOf('Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMariaDb', $container->get('example')); + $this->assertSame('Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMariaDb', $container->getDefinition('mariadb.example')->getClass()); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index c8820d5d59814..701fe1b188538 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -20,8 +20,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\RuntimeException; -use Symfony\Component\DependencyInjection\Exception\InactiveScopeException; -use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; use Symfony\Component\DependencyInjection\Reference; @@ -76,6 +74,9 @@ public function testCreateDeprecatedService() $builder = new ContainerBuilder(); $builder->setDefinition('deprecated_foo', $definition); + + $builder->compile(); + $builder->get('deprecated_foo'); restore_error_handler(); @@ -102,34 +103,71 @@ public function testHas() $this->assertTrue($builder->has('bar'), '->has() returns true if a service exists'); } - public function testGet() + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + * @expectedExceptionMessage You have requested a non-existent service "foo". + */ + public function testGetThrowsExceptionIfServiceDoesNotExist() { $builder = new ContainerBuilder(); - try { - $builder->get('foo'); - $this->fail('->get() throws a ServiceNotFoundException if the service does not exist'); - } catch (ServiceNotFoundException $e) { - $this->assertEquals('You have requested a non-existent service "foo".', $e->getMessage(), '->get() throws a ServiceNotFoundException if the service does not exist'); - } + $builder->compile(); + $builder->get('foo'); + } + + public function testGetReturnsNullIfServiceDoesNotExistAndInvalidReferenceIsUsed() + { + $builder = new ContainerBuilder(); + $builder->compile(); $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'); + } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException + */ + public function testGetThrowsCircularReferenceExceptionIfServiceHasReferenceToItself() + { + $builder = new ContainerBuilder(); + $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz'))); + $builder->compile(); + $builder->get('baz'); + } + + public function testGetReturnsSameInstanceWhenServiceIsShared() + { + $builder = new ContainerBuilder(); + $builder->register('bar', 'stdClass'); + $builder->compile(); + + $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared'); + } + + public function testGetCreatesServiceBasedOnDefinition() + { + $builder = new ContainerBuilder(); $builder->register('foo', 'stdClass'); + $builder->compile(); + $this->assertInternalType('object', $builder->get('foo'), '->get() returns the service definition associated with the id'); + } + + public function testGetReturnsRegisteredService() + { + $builder = new ContainerBuilder(); $builder->set('bar', $bar = new \stdClass()); - $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id'); - $builder->register('bar', 'stdClass'); - $this->assertEquals($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined'); + $builder->compile(); - $builder->register('baz', 'stdClass')->setArguments(array(new Reference('baz'))); - try { - @$builder->get('baz'); - $this->fail('->get() throws a ServiceCircularReferenceException if the service has a circular reference to itself'); - } catch (\Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException $e) { - $this->assertEquals('Circular reference detected for service "baz", path: "baz".', $e->getMessage(), '->get() throws a LogicException if the service has a circular reference to itself'); - } + $this->assertSame($bar, $builder->get('bar'), '->get() returns the service associated with the id'); + } - $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared'); + public function testRegisterDoesNotOverrideExistingService() + { + $builder = new ContainerBuilder(); + $builder->set('bar', $bar = new \stdClass()); + $builder->register('bar', 'stdClass'); + $builder->compile(); + + $this->assertSame($bar, $builder->get('bar'), '->get() returns the service associated with the id even if a definition has been defined'); } public function testNonSharedServicesReturnsDifferentInstances() @@ -137,6 +175,8 @@ public function testNonSharedServicesReturnsDifferentInstances() $builder = new ContainerBuilder(); $builder->register('bar', 'stdClass')->setShared(false); + $builder->compile(); + $this->assertNotSame($builder->get('bar'), $builder->get('bar')); } @@ -149,6 +189,8 @@ public function testGetUnsetLoadingServiceWhenCreateServiceThrowsAnException() $builder = new ContainerBuilder(); $builder->register('foo', 'stdClass')->setSynthetic(true); + $builder->compile(); + // we expect a RuntimeException here as foo is synthetic try { $builder->get('foo'); @@ -177,6 +219,9 @@ public function testAliases() $this->assertFalse($builder->hasAlias('foobar'), '->hasAlias() returns false if the alias does not exist'); $this->assertEquals('foo', (string) $builder->getAlias('bar'), '->getAlias() returns the aliased service'); $this->assertTrue($builder->has('bar'), '->setAlias() defines a new service'); + + $builder->compile(); + $this->assertTrue($builder->get('bar') === $builder->get('foo'), '->setAlias() creates a service that is an alias to another one'); try { @@ -244,6 +289,9 @@ public function testSetReplacesAlias() $builder->set('aliased', new \stdClass()); $builder->set('alias', $foo = new \stdClass()); + + $builder->compile(); + $this->assertSame($foo, $builder->get('alias'), '->set() replaces an existing alias'); } @@ -261,9 +309,12 @@ public function testCreateService() { $builder = new ContainerBuilder(); $builder->register('foo1', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); - $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition'); $builder->register('foo2', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/%file%.php'); $builder->setParameter('file', 'foo'); + + $builder->compile(); + + $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo1'), '->createService() requires the file defined by the service definition'); $this->assertInstanceOf('\Bar\FooClass', $builder->get('foo2'), '->createService() replaces parameters in the file provided by the service definition'); } @@ -274,6 +325,8 @@ public function testCreateProxyWithRealServiceInstantiator() $builder->register('foo1', 'Bar\FooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); $builder->getDefinition('foo1')->setLazy(true); + $builder->compile(); + $foo1 = $builder->get('foo1'); $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls'); @@ -285,6 +338,9 @@ public function testCreateServiceClass() $builder = new ContainerBuilder(); $builder->register('foo1', '%class%'); $builder->setParameter('class', 'stdClass'); + + $builder->compile(); + $this->assertInstanceOf('\stdClass', $builder->get('foo1'), '->createService() replaces parameters in the class provided by the service definition'); } @@ -294,6 +350,9 @@ public function testCreateServiceArguments() $builder->register('bar', 'stdClass'); $builder->register('foo1', 'Bar\FooClass')->addArgument(array('foo' => '%value%', '%value%' => 'foo', new Reference('bar'), '%%unescape_it%%')); $builder->setParameter('value', 'bar'); + + $builder->compile(); + $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'); } @@ -305,6 +364,8 @@ public function testCreateServiceFactory() $builder->register('bar', 'Bar\FooClass')->setFactory(array(new Definition('Bar\FooClass'), 'getInstance')); $builder->register('baz', 'Bar\FooClass')->setFactory(array(new Reference('bar'), 'getInstance')); + $builder->compile(); + $this->assertTrue($builder->get('foo')->called, '->createService() calls the factory method to create the service instance'); $this->assertTrue($builder->get('qux')->called, '->createService() calls the factory method to create the service instance'); $this->assertTrue($builder->get('bar')->called, '->createService() uses anonymous service as factory'); @@ -317,6 +378,9 @@ public function testCreateServiceMethodCalls() $builder->register('bar', 'stdClass'); $builder->register('foo1', 'Bar\FooClass')->addMethodCall('setBar', array(array('%value%', new Reference('bar')))); $builder->setParameter('value', 'bar'); + + $builder->compile(); + $this->assertEquals(array('bar', $builder->get('bar')), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments'); } @@ -326,6 +390,9 @@ public function testCreateServiceMethodCallsWithEscapedParam() $builder->register('bar', 'stdClass'); $builder->register('foo1', 'Bar\FooClass')->addMethodCall('setBar', array(array('%%unescape_it%%'))); $builder->setParameter('value', 'bar'); + + $builder->compile(); + $this->assertEquals(array('%unescape_it%'), $builder->get('foo1')->bar, '->createService() replaces the values in the method calls arguments'); } @@ -335,6 +402,9 @@ public function testCreateServiceProperties() $builder->register('bar', 'stdClass'); $builder->register('foo1', 'Bar\FooClass')->setProperty('bar', array('%value%', new Reference('bar'), '%%unescape_it%%')); $builder->setParameter('value', 'bar'); + + $builder->compile(); + $this->assertEquals(array('bar', $builder->get('bar'), '%unescape_it%'), $builder->get('foo1')->bar, '->createService() replaces the values in the properties'); } @@ -342,20 +412,20 @@ public function testCreateServiceConfigurator() { $builder = new ContainerBuilder(); $builder->register('foo1', 'Bar\FooClass')->setConfigurator('sc_configure'); - $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator'); - $builder->register('foo2', 'Bar\FooClass')->setConfigurator(array('%class%', 'configureStatic')); $builder->setParameter('class', 'BazClass'); - $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator'); - $builder->register('baz', 'BazClass'); $builder->register('foo3', 'Bar\FooClass')->setConfigurator(array(new Reference('baz'), 'configure')); - $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator'); - $builder->register('foo4', 'Bar\FooClass')->setConfigurator(array($builder->getDefinition('baz'), 'configure')); + $builder->register('foo5', 'Bar\FooClass')->setConfigurator('foo'); + + $builder->compile(); + + $this->assertTrue($builder->get('foo1')->configured, '->createService() calls the configurator'); + $this->assertTrue($builder->get('foo2')->configured, '->createService() calls the configurator'); + $this->assertTrue($builder->get('foo3')->configured, '->createService() calls the configurator'); $this->assertTrue($builder->get('foo4')->configured, '->createService() calls the configurator'); - $builder->register('foo5', 'Bar\FooClass')->setConfigurator('foo'); try { $builder->get('foo5'); $this->fail('->createService() throws an InvalidArgumentException if the configure callable is not a valid callable'); @@ -371,6 +441,9 @@ public function testCreateSyntheticService() { $builder = new ContainerBuilder(); $builder->register('foo', 'Bar\FooClass')->setSynthetic(true); + + $builder->compile(); + $builder->get('foo'); } @@ -380,6 +453,9 @@ public function testCreateServiceWithExpression() $builder->setParameter('bar', 'bar'); $builder->register('bar', 'BarClass'); $builder->register('foo', 'Bar\FooClass')->addArgument(array('foo' => new Expression('service("bar").foo ~ parameter("bar")'))); + + $builder->compile(); + $this->assertEquals('foobar', $builder->get('foo')->arguments['foo']); } @@ -387,6 +463,8 @@ public function testResolveServices() { $builder = new ContainerBuilder(); $builder->register('foo', 'Bar\FooClass'); + $builder->compile(); + $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Reference('foo')), '->resolveServices() resolves service references to service instances'); $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'); $this->assertEquals($builder->get('foo'), $builder->resolveServices(new Expression('service("foo")')), '->resolveServices() resolves expressions'); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy