From 432a723a7c9420bad08ae654dce77771cad43e98 Mon Sep 17 00:00:00 2001 From: Jake Whiteley Date: Mon, 16 May 2022 22:26:13 +0100 Subject: [PATCH] Add support for scalar typehinting --- src/Container.php | 26 ++++++++++++++++---------- src/ContainerArrayAccess.php | 18 +++++++++--------- tests/Classes/PrimitivesTest.php | 13 +++++++++++++ tests/ContainerTest.php | 13 +++++++++++++ 4 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 tests/Classes/PrimitivesTest.php diff --git a/src/Container.php b/src/Container.php index b6e8bdd..465743c 100644 --- a/src/Container.php +++ b/src/Container.php @@ -333,29 +333,35 @@ private function resolveFromContainer(string $className): bool private function resolveParams(array $params, array $args): void { foreach ($params as $param) { - $class = $param->getType(); + $reflectionType = $param->getType(); - // if the param is not a class, check $args for the value - if (\is_null($class)) { + // if the param is not type-hinted, check $args for the value + if (\is_null($reflectionType)) { $this->resolveParam($args, $param); continue; } - $className = $class->getName(); + $typeName = $reflectionType->getName(); // if the class exists in the container, inject it - if ($this->resolveFromContainer($className)) { + if ($this->resolveFromContainer($typeName)) { continue; } - $reflectionClass = new ReflectionClass($className); + if (class_exists($typeName) || interface_exists($typeName)) { + $reflectionClass = new ReflectionClass($typeName); - if ($reflectionClass->isInterface()) { - throw new ConcreteClassNotFoundException("$className is an interface with no bound implementation."); + if ($reflectionClass->isInterface()) { + throw new ConcreteClassNotFoundException("$typeName is an interface with no bound implementation."); + } + + // else the param is a class, so run $this->resolve on it + $this->addToStack($this->resolve($typeName, $args)); + continue; } - // else the param is a class, so run $this->resolve on it - $this->addToStack($this->resolve($className, $args)); + // It was type-hinted but not a defined class, so assume it's a primitive and try to resolve + $this->resolveParam($args, $param); } } diff --git a/src/ContainerArrayAccess.php b/src/ContainerArrayAccess.php index 47f710c..666eada 100644 --- a/src/ContainerArrayAccess.php +++ b/src/ContainerArrayAccess.php @@ -3,9 +3,10 @@ namespace Hodl; use ArrayAccess; +use Closure; /** - * ArrayAccess implementaion for Hodl\Container + * ArrayAccess implementation for Hodl\Container */ class ContainerArrayAccess implements ArrayAccess { @@ -13,9 +14,9 @@ class ContainerArrayAccess implements ArrayAccess * Sets the value at specified offset. * * @param string $offset The key to set - * @param \closure $value The value to set + * @param Closure $value The value to set */ - public function offsetSet($offset, $value) + public function offsetSet($offset, $value): void { $this->add($offset, $value); } @@ -26,7 +27,7 @@ public function offsetSet($offset, $value) * @param string $offset The key to set * @return bool */ - public function offsetExists($offset) + public function offsetExists($offset): bool { return $this->has($offset); } @@ -35,9 +36,9 @@ public function offsetExists($offset) * Gets the value at specified offset. * * @param string $offset The key to get - * @return object|closure $value The object instance or closure if a factory class + * @return object $value The object instance or closure if a factory class */ - public function offsetGet($offset) + public function offsetGet($offset): object { return $this->get($offset); } @@ -46,10 +47,9 @@ public function offsetGet($offset) * Unsets the value at specified offset. * * @param string $offset The key to set - * @return bool */ - public function offsetUnset($offset) + public function offsetUnset($offset): void { - return $this->remove($offset); + $this->remove($offset); } } diff --git a/tests/Classes/PrimitivesTest.php b/tests/Classes/PrimitivesTest.php new file mode 100644 index 0000000..2282667 --- /dev/null +++ b/tests/Classes/PrimitivesTest.php @@ -0,0 +1,13 @@ +foo = $string; + } +} diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index 97c9e59..ac8cdae 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -16,6 +16,7 @@ use Hodl\Tests\Classes\NeedsResolving; use Hodl\Tests\Classes\NeedsServiceAndConstructorParams; use Hodl\Tests\Classes\NoConstructor; +use Hodl\Tests\Classes\PrimitivesTest; use Hodl\Tests\Classes\Resolver; use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; @@ -205,6 +206,18 @@ public function an_object_can_be_resolved_explicitly_with_params(): void $this->assertEquals('has_been_set', $doesntNeedResolving->foo); } + /** + * @test + */ + public function an_object_can_be_resolved_explicitly_with_typehinted_primitive_params(): void + { + $hodl = new Container(); + + $doesntNeedResolving = $hodl->resolve(PrimitivesTest::class, ['string' => 'has_been_set']); + + $this->assertEquals('has_been_set', $doesntNeedResolving->foo); + } + /** * @test */