entries = $entries; $factories = []; foreach ($providers as $provider) { /** @var ServiceProviderInterface $provider */ $factories = $provider->getFactories() + $factories; foreach ($provider->getExtensions() as $id => $extension) { // Decorate a previously defined extension or if that is not available, // create a lazy lookup to a factory from the list of vanilla factories. // Lazy because we currently can not know whether a factory will only // become available due to a subsequent provider. $innerFactory = $this->factories[$id] ?? static function (ContainerInterface $c) use (&$factories, $id) { return isset($factories[$id]) ? $factories[$id]($c) : null; }; $this->factories[$id] = static function (ContainerInterface $container) use ($extension, $innerFactory) { $previous = $innerFactory($container); return $extension($container, $previous); }; } } // Add factories to the list of factories for services that were not extended. // (i.e those that have not been specified in getExtensions) $this->factories += $factories; } public function has(string $id): bool { return array_key_exists($id, $this->entries) || array_key_exists($id, $this->factories); } /** * @return mixed */ private function create(string $id) { $factory = $this->factories[$id] ?? null; if ((bool)$factory) { // Remove factory as it is no longer required. // Set factory to false to be able to detect // cyclic dependency loops. $this->factories[$id] = false; return $this->entries[$id] = $factory($this); } if (array_key_exists($id, $this->entries)) { // This condition is triggered in the unlikely case that the entry is null // Note: That is because the coalesce operator used in get() can not handle that return $this->entries[$id]; } if ($factory === null) { throw new NotFoundException('Container entry "' . $id . '" is not available.', 1519978105); } // if ($factory === false) throw new ContainerException('Container entry "' . $id . '" is part of a cyclic dependency chain.', 1520175002); } /** * @return mixed */ public function get(string $id) { return $this->entries[$id] ?? $this->create($id); } }