diff --git a/src/DI/Container.php b/src/DI/Container.php index b726587ca..6d2a871ad 100644 --- a/src/DI/Container.php +++ b/src/DI/Container.php @@ -41,9 +41,12 @@ class Container /** @var array circular reference detector */ private array $creating; - /** @var array */ + /** @var array */ private array $methods; + /** @var array service name => \Closure */ + private array $factories = []; + public function __construct(array $params = []) { @@ -110,7 +113,7 @@ public function addService(string $name, object $service): static } if ($service instanceof \Closure) { - $this->methods[self::getMethodName($name)] = $service; + $this->factories[$name] = $service; $this->types[$name] = $type; } else { $this->instances[$name] = $service; @@ -175,6 +178,9 @@ public function getServiceType(string $name): string } elseif (isset($this->methods[$method])) { return (string) (new \ReflectionMethod($this, $method))->getReturnType(); + } elseif ($cb = $this->factories[$name] ?? null) { + return (string) (new \ReflectionFunction($cb))->getReturnType(); + } else { throw new MissingServiceException(sprintf("Service '%s' not found.", $name)); } @@ -187,7 +193,7 @@ public function getServiceType(string $name): string public function hasService(string $name): bool { $name = $this->aliases[$name] ?? $name; - return isset($this->methods[self::getMethodName($name)]) || isset($this->instances[$name]); + return isset($this->methods[self::getMethodName($name)]) || isset($this->instances[$name]) || isset($this->factories[$name]); } @@ -213,15 +219,14 @@ public function createService(string $name): object { $name = $this->aliases[$name] ?? $name; $method = self::getMethodName($name); - $callback = $this->methods[$method] ?? null; - if ($callback === null) { + if ($callback = ($this->factories[$name] ?? null)) { + $service = $this->preventDeadLock($name, fn() => $callback()); + } elseif (isset($this->methods[$method])) { + $service = $this->preventDeadLock($name, fn() => $this->$method()); + } else { throw new MissingServiceException(sprintf("Service '%s' not found.", $name)); } - $service = $this->preventDeadLock($name, fn() => $callback instanceof \Closure - ? $callback() - : $this->$method()); - if (!is_object($service)) { throw new Nette\UnexpectedValueException(sprintf( "Unable to create service '$name', value returned by %s is not object.",