diff --git a/README.md b/README.md index c5239e1..3d9ab17 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ To retrieve a service from the container, use the `get` method: ```php -$myService = $container->get('myService'); +$myService = $container->get(MyService::class); ``` ### Invoking Methods @@ -75,7 +75,10 @@ #### Methods - `__construct(array $definitions = [])`: Creates a new container with optional initial service definitions. +- `value(string $name, mixed $value): self`: Define a value to be stored in the container. +- `alias(string $name, string $alias): self`: Define an alias for a name in the container. - `set(string $name, string|callable $value, array $constants = [], bool $singleton = false): self`: Defines a service in the container. +- `has(string $id): bool`: Returns true if the container can return an entry for the given identifier. - `get(string $id): mixed`: Retrieves a service from the container. - `invoke(string|object $entry, string $method = '__invoke', array $constants = []): mixed`: Invokes a method on an object. diff --git a/composer.json b/composer.json index 9b4d8c6..4a40ad7 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "uid/lib-di-container", "type": "library", - "description": "simple implementation of PSR-11: Container", + "description": "A simple implementation of PSR-11: Container.", "keywords": ["psr-11", "di", "container"], "license": "Apache-2.0", "autoload": { diff --git a/src/Container/Container.php b/src/Container/Container.php index 624bf77..a27dfee 100644 --- a/src/Container/Container.php +++ b/src/Container/Container.php @@ -11,11 +11,9 @@ use function array_key_exists; use function array_map; use function class_exists; -use function class_implements; -use function class_parents; use function count; use function get_class; -use function in_array; +use function is_a; use function is_object; use function is_string; use function method_exists; @@ -44,7 +42,7 @@ * @param mixed $value The value to store. * @return Container The container instance. */ - public function value(string $name, $value): self + public function value(string $name, mixed $value): self { $this->definitions[$name] = ['value' => $value]; return $this; @@ -108,7 +106,9 @@ /** @inheritdoc*/ public function has(string $id): bool { - return $this->definition($this->resolve($id)) !== null; + //return $this->definition($this->resolve($id)) !== null; + $name = $this->resolve($id); + return array_key_exists($name, $this->definitions) || class_exists($name); } /** @inheritdoc*/ public function get(string $id): mixed @@ -142,8 +142,14 @@ } catch (ReflectionException $ex) { throw new ContainerException(sprintf("Unable to invoke method '%s' for instance of '%s'", $method, get_class($object)), 0, $ex); } - $arguments = array_map(fn($parameter) => $this->argument($parameter, $constants), $reflection->getParameters()); - return $object->$method(... array_map(fn($arg) => $arg[0] ? $this->get($arg[1]): $arg[1], $arguments)); + $arguments = array_map( + fn($parameter) => $this->argument($parameter, $constants), + $reflection->getParameters() + ); + return $object->$method(... array_map( + fn($arg) => $arg[0] ? $this->get($arg[1]): $arg[1], + $arguments + )); } /** * Get the definition for the given entry name. @@ -195,9 +201,15 @@ } $arguments = []; if (($constructor = $reflection->getConstructor())) { - $arguments = array_map(fn($parameter) => $this->argument($parameter, $constants), $constructor->getParameters()); + $arguments = array_map( + fn($parameter) => $this->argument($parameter, $constants), + $constructor->getParameters() + ); } - return fn(Container $container) => new $class(... array_map(fn($arg) => $arg[0] ? $container->get($arg[1]) : $arg[1], $arguments)); + return fn(Container $container) => new $class(... array_map( + fn($arg) => $arg[0] ? $container->get($arg[1]) : $arg[1], + $arguments + )); } /** * Create a callback for the given callable. @@ -217,11 +229,17 @@ if (empty($parameters)) { return $callback; } - if (count($parameters) === 1 && self::isImplements($parameters[0]->getType(), self::class)) { + if (count($parameters) === 1 && is_a($this, $parameters[0]->getType())) { return $callback; } - $arguments = array_map(fn($parameter) => $this->argument($parameter, $constants), $parameters); - return fn(Container $container) => $callback(... array_map(fn($arg) => $arg[0] ? $container->get($arg[1]): $arg[1], $arguments)); + $arguments = array_map( + fn($parameter) => $this->argument($parameter, $constants), + $parameters + ); + return fn(Container $container) => $callback(... array_map( + fn($arg) => $arg[0] ? $container->get($arg[1]): $arg[1], + $arguments + )); } /** * Resolve the argument for a parameter. @@ -243,11 +261,4 @@ } throw new ContainerException(sprintf("Failed to process a parameter: '%s' of type '%s'", $name, $type)); } - - private static function isImplements(string $type, string $class): bool - { - return $type == $class - || in_array($type, class_parents($class)) - || in_array($type, class_implements($class)); - } } diff --git a/tests/Container/ContainerTest.php b/tests/Container/ContainerTest.php index af4e6d4..2ff5fac 100644 --- a/tests/Container/ContainerTest.php +++ b/tests/Container/ContainerTest.php @@ -49,11 +49,13 @@ $container = (new Container()) ->factory(ContainerTest::class, fn() => new ContainerTest(), [], true) ->factory('Service1', fn(ContainerInterface $container) => $container->get(ContainerTest::class)) - ->factory('Service2', fn(ContainerTest $class) => $class); + ->factory('Service2', fn(ContainerTest $class) => $class) + ->factory('Service3', fn(Container $class) => $class); $this->assertInstanceOf(ContainerTest::class, $container->get(ContainerTest::class)); $this->assertInstanceOf(ContainerTest::class, $container->get('Service1')); $this->assertInstanceOf(ContainerTest::class, $container->get('Service2')); + $this->assertInstanceOf(Container::class, $container->get('Service3')); } public function testSingleton()