diff --git a/src/ServiceManager.php b/src/ServiceManager.php index 4746f082..457a9519 100644 --- a/src/ServiceManager.php +++ b/src/ServiceManager.php @@ -211,6 +211,11 @@ public function get($name) // We now deal with requests which may be aliases. $resolvedName = isset($this->aliases[$name]) ? $this->aliases[$name] : $name; + // Update shared service information as we checked if the alias was shared before. + if ($resolvedName !== $name) { + $sharedService = $this->shared[$resolvedName] ?? $sharedService; + } + // The following is only true if the requested service is a shared alias. $sharedAlias = $sharedService && isset($this->services[$resolvedName]); diff --git a/test/ServiceManagerTest.php b/test/ServiceManagerTest.php index 5e66363c..7562ad3b 100644 --- a/test/ServiceManagerTest.php +++ b/test/ServiceManagerTest.php @@ -476,4 +476,92 @@ static function (object $service) use (&$initializerTwoCalled): object { self::assertTrue($initializerOneCalled, 'First initializer was not called'); self::assertTrue($initializerTwoCalled, 'Second initializer was not called'); } + + /** + * @param array $config + * @param non-empty-string $serviceName + * @param non-empty-string $alias + * @dataProvider aliasedServices + */ + public function testWontShareServiceWhenRequestedByAlias(array $config, string $serviceName, string $alias): void + { + $serviceManager = new ServiceManager($config); + $service = $serviceManager->get($serviceName); + $serviceFromAlias = $serviceManager->get($alias); + $serviceFromServiceNameAfterUsingAlias = $serviceManager->get($serviceName); + + self::assertNotSame($service, $serviceFromAlias); + self::assertNotSame($service, $serviceFromServiceNameAfterUsingAlias); + self::assertNotSame($serviceFromAlias, $serviceFromServiceNameAfterUsingAlias); + } + + /** + * @return array,1:non-empty-string,2:non-empty-string}> + */ + public function aliasedServices(): array + { + return [ + 'invokables' => [ + [ + 'invokables' => [ + stdClass::class => stdClass::class, + ], + 'aliases' => [ + 'object' => stdClass::class, + ], + 'shared' => [ + stdClass::class => false, + ], + ], + stdClass::class, + 'object', + ], + 'factories' => [ + [ + 'factories' => [ + stdClass::class => static function (): stdClass { + return new stdClass(); + }, + ], + 'aliases' => [ + 'object' => stdClass::class, + ], + 'shared' => [ + stdClass::class => false, + ], + ], + stdClass::class, + 'object', + ], + 'abstract factories' => [ + [ + 'abstract_factories' => [ + new class implements AbstractFactoryInterface { + + public function canCreate(\Interop\Container\ContainerInterface $container, $requestedName) + { + return $requestedName === stdClass::class; + } + + public function __invoke( + \Interop\Container\ContainerInterface $container, + $requestedName, + array $options = null + ) { + return new stdClass(); + } + } + ], + 'aliases' => [ + 'object' => stdClass::class, + ], + 'shared' => [ + stdClass::class => false, + ], + ], + stdClass::class, + 'object', + ], + ]; + } }