diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 485630a74876..db1ea84c2cf7 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -546,8 +546,8 @@ public function has(string $id) */ public function get(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - if ($this->isCompiled() && isset($this->removedIds[$id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) { - return parent::get($id); + if ($this->isCompiled() && isset($this->removedIds[$id])) { + return ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior ? parent::get($id) : null; } return $this->doGet($id, $invalidBehavior); @@ -564,9 +564,9 @@ private function doGet(string $id, int $invalidBehavior = ContainerInterface::EX } try { if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) { - return parent::get($id, $invalidBehavior); + return $this->privates[$id] ?? parent::get($id, $invalidBehavior); } - if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { + if (null !== $service = $this->privates[$id] ?? parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { return $service; } } catch (ServiceCircularReferenceException $e) { @@ -1085,8 +1085,8 @@ private function createService(Definition $definition, array &$inlineServices, b } } - if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) { - return $this->services[$id]; + if (null !== $id && $definition->isShared() && (isset($this->services[$id]) || isset($this->privates[$id])) && ($tryProxy || !$definition->isLazy())) { + return $this->services[$id] ?? $this->privates[$id]; } if (null !== $factory) { @@ -1665,7 +1665,11 @@ private function shareService(Definition $definition, $service, ?string $id, arr $inlineServices[$id ?? spl_object_hash($definition)] = $service; if (null !== $id && $definition->isShared()) { - $this->services[$id] = $service; + if ($definition->isPrivate() && $this->isCompiled()) { + $this->privates[$id] = $service; + } else { + $this->services[$id] = $service; + } unset($this->loading[$id]); } } diff --git a/src/Symfony/Component/DependencyInjection/ReverseContainer.php b/src/Symfony/Component/DependencyInjection/ReverseContainer.php index 280e9e2dd5a6..e5207e56dcf7 100644 --- a/src/Symfony/Component/DependencyInjection/ReverseContainer.php +++ b/src/Symfony/Component/DependencyInjection/ReverseContainer.php @@ -63,10 +63,6 @@ public function getId(object $service): ?string */ public function getService(string $id): object { - if ($this->serviceContainer->has($id)) { - return $this->serviceContainer->get($id); - } - if ($this->reversibleLocator->has($id)) { return $this->reversibleLocator->get($id); } @@ -75,7 +71,6 @@ public function getService(string $id): object throw new ServiceNotFoundException($id, null, null, [], sprintf('The "%s" service is private and cannot be accessed by reference. You should either make it public, or tag it as "%s".', $id, $this->tagName)); } - // will throw a ServiceNotFoundException - $this->serviceContainer->get($id); + return $this->serviceContainer->get($id); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index e491e2c79017..1dfd8f86eaf4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1105,10 +1105,19 @@ public function testPrivateServiceUser() $container->addDefinitions([ 'bar' => $fooDefinition, 'bar_user' => $fooUserDefinition->setPublic(true), + 'bar_user2' => $fooUserDefinition->setPublic(true), ]); $container->compile(); + $this->assertNull($container->get('bar', $container::NULL_ON_INVALID_REFERENCE)); $this->assertInstanceOf(\BarClass::class, $container->get('bar_user')->bar); + + // Ensure that accessing a public service with a shared private service + // does not make the private service available. + $this->assertNull($container->get('bar', $container::NULL_ON_INVALID_REFERENCE)); + + // Ensure the private service is still shared. + $this->assertSame($container->get('bar_user')->bar, $container->get('bar_user2')->bar); } public function testThrowsExceptionWhenSetServiceOnACompiledContainer()