Skip to content
This repository was archived by the owner on Feb 6, 2020. It is now read-only.

Commit 5108bca

Browse files
committed
Use default values for type-hinted arguments if type not found in container
Per #239, currently when an argument is type-hinted but has a default value (typically `null`), the factory raises an exception about not being able to retrieve the value from the container. In such cases, we can use the default value for the argument during injection.
1 parent e11039a commit 5108bca

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

src/AbstractFactory/ReflectionBasedAbstractFactory.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,11 @@ private function resolveParameter(ReflectionParameter $parameter, ContainerInter
218218
$type = $parameter->getClass()->getName();
219219
$type = isset($this->aliases[$type]) ? $this->aliases[$type] : $type;
220220

221-
if (! $container->has($type)) {
221+
if ($container->has($type)) {
222+
return $container->get($type);
223+
}
224+
225+
if (! $parameter->isOptional()) {
222226
throw new ServiceNotFoundException(sprintf(
223227
'Unable to create service "%s"; unable to resolve parameter "%s" using type hint "%s"',
224228
$requestedName,
@@ -227,6 +231,8 @@ private function resolveParameter(ReflectionParameter $parameter, ContainerInter
227231
));
228232
}
229233

230-
return $container->get($type);
234+
// Type not available in container, but the value is optional and has a
235+
// default defined.
236+
return $parameter->getDefaultValue();
231237
}
232238
}

test/AbstractFactory/ReflectionBasedAbstractFactoryTest.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
namespace ZendTest\ServiceManager\AbstractFactory;
99

10+
use ArrayAccess;
1011
use Interop\Container\ContainerInterface;
1112
use PHPUnit\Framework\TestCase;
1213
use Zend\ServiceManager\AbstractFactory\ReflectionBasedAbstractFactory;
@@ -154,4 +155,20 @@ public function testFactoryWillUseDefaultValueWhenPresentForScalarArgument()
154155
$this->assertInstanceOf(TestAsset\ClassWithScalarDependencyDefiningDefaultValue::class, $instance);
155156
$this->assertEquals('bar', $instance->foo);
156157
}
158+
159+
/**
160+
* @see https://github.com/zendframework/zend-servicemanager/issues/239
161+
*/
162+
public function testFactoryWillUseDefaultValueForTypeHintedArgument()
163+
{
164+
$this->container->has('config')->willReturn(false);
165+
$this->container->has(ArrayAccess::class)->willReturn(false);
166+
$factory = new ReflectionBasedAbstractFactory();
167+
$instance = $factory(
168+
$this->container->reveal(),
169+
TestAsset\ClassWithTypehintedDefaultValue::class
170+
);
171+
$this->assertInstanceOf(TestAsset\ClassWithTypehintedDefaultValue::class, $instance);
172+
$this->assertNull($instance->value);
173+
}
157174
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-2018 for the canonical source repository
4+
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (https://www.zend.com)
5+
* @license https://github.com/zendframework/zend-2018/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace ZendTest\ServiceManager\AbstractFactory\TestAsset;
9+
10+
use ArrayAccess;
11+
12+
class ClassWithTypehintedDefaultValue
13+
{
14+
public $value;
15+
16+
public function __construct(ArrayAccess $value = null)
17+
{
18+
$this->value = null;
19+
}
20+
}

0 commit comments

Comments
 (0)