Skip to content

Commit 2e8b557

Browse files
committed
Merge pull request laravel#1690 from kdocki/master
IoC container not resolving classes with optional parameters (i.e. models that use Eloquent)
2 parents 23d23dd + 1ed7ec9 commit 2e8b557

File tree

2 files changed

+114
-9
lines changed

2 files changed

+114
-9
lines changed

laravel/ioc.php

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ protected static function build($type, $parameters = array())
172172
return new $type;
173173
}
174174

175-
$dependencies = static::dependencies($constructor->getParameters());
175+
$dependencies = static::dependencies($constructor->getParameters(), $parameters);
176176

177177
return $reflector->newInstanceArgs($dependencies);
178178
}
@@ -181,28 +181,54 @@ protected static function build($type, $parameters = array())
181181
* Resolve all of the dependencies from the ReflectionParameters.
182182
*
183183
* @param array $parameters
184+
* @param array $arguments that might have been passed into our resolve
184185
* @return array
185186
*/
186-
protected static function dependencies($parameters)
187+
protected static function dependencies($parameters, $arguments)
187188
{
188189
$dependencies = array();
189190

190191
foreach ($parameters as $parameter)
191192
{
192193
$dependency = $parameter->getClass();
193194

194-
// If the class is null, it means the dependency is a string or some other
195-
// primitive type, which we can not resolve since it is not a class and
196-
// we'll just bomb out with an error since we have nowhere to go.
197-
if (is_null($dependency))
195+
// If the person passed in some parameters to the class
196+
// then we should probably use those instead of trying
197+
// to resolve a new instance of the class
198+
if (count($arguments) > 0)
198199
{
199-
throw new \Exception("Unresolvable dependency resolving [$parameter].");
200+
$dependencies[] = array_shift($arguments);
201+
}
202+
else if (is_null($dependency))
203+
{
204+
$dependency[] = static::resolveNonClass($parameter);
205+
}
206+
else
207+
{
208+
$dependencies[] = static::resolve($dependency->name);
200209
}
201-
202-
$dependencies[] = static::resolve($dependency->name);
203210
}
204211

205212
return (array) $dependencies;
206213
}
207214

215+
/**
216+
* Resolves optional parameters for our dependency injection
217+
* pretty much took backport straight from L4's Illuminate\Container
218+
*
219+
* @param ReflectionParameter
220+
* @return default value
221+
*/
222+
protected static function resolveNonClass($parameter)
223+
{
224+
if ($parameter->isDefaultValueAvailable())
225+
{
226+
return $parameter->getDefaultValue();
227+
}
228+
else
229+
{
230+
throw new \Exception("Unresolvable dependency resolving [$parameter].");
231+
}
232+
}
233+
208234
}

laravel/tests/cases/ioc.test.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,34 @@
11
<?php
22

3+
/**
4+
* Testing Optional Parameters in classes' Dependency Injection
5+
*/
6+
class TestOptionalParamClassForIoC
7+
{
8+
public function __construct($optional_param = 42) {}
9+
}
10+
11+
/**
12+
* Testing Dependency Injection with this class
13+
*/
14+
class TestClassOneForIoC
15+
{
16+
public $_variable;
17+
}
18+
19+
/**
20+
* Testing Dependency Injection of ClassOne
21+
*/
22+
class TestClassTwoForIoC
23+
{
24+
public $class_one;
25+
public function __construct(TestClassOneForIoC $class_one)
26+
{
27+
$this->class_one = $class_one;
28+
}
29+
}
30+
31+
332
class IoCTest extends PHPUnit_Framework_TestCase {
433

534
/**
@@ -71,4 +100,54 @@ public function testControllerMethodRegistersAController()
71100
$this->assertTrue(IoC::registered('controller: ioc.test'));
72101
}
73102

103+
/**
104+
* Test that classes with optional parameters can resolve
105+
*/
106+
public function testOptionalParamClassResolves()
107+
{
108+
$test = IoC::resolve('TestOptionalParamClassForIoC');
109+
$this->assertInstanceOf('TestOptionalParamClassForIoC', $test);
110+
}
111+
112+
/**
113+
* Test that we can resolve TestClassOneForIoC using IoC
114+
*/
115+
public function testClassOneForIoCResolves()
116+
{
117+
$test = IoC::resolve('TestClassOneForIoC');
118+
$this->assertInstanceOf('TestClassOneForIoC', $test);
119+
}
120+
121+
/**
122+
* Test that we can resolve TestClassTwoForIoC
123+
*/
124+
public function testClassTwoForIoCResolves()
125+
{
126+
$test = IoC::resolve('TestClassTwoForIoC');
127+
$this->assertInstanceOf('TestClassTwoForIoC', $test);
128+
}
129+
130+
/**
131+
* Test that when we resolve TestClassTwoForIoC we auto resolve
132+
* the dependency for TestClassOneForIoC
133+
*/
134+
public function testClassTwoResolvesClassOneDependency()
135+
{
136+
$test = IoC::resolve('TestClassTwoForIoC');
137+
$this->assertInstanceOf('TestClassOneForIoC', $test->TestClassOneForIoC);
138+
}
139+
140+
/**
141+
* Test that when we resolve TestClassTwoForIoC with a parameter
142+
* that it actually uses that instead of a blank class TestClassOneForIoC
143+
*/
144+
public function testClassTwoResolvesClassOneWithArgument()
145+
{
146+
$class_one = IoC::resolve('TestClassOneForIoC');
147+
$class_one->test_variable = 42;
148+
149+
$class_two = IoC::resolve('TestClassTwoForIoC', [$class_one]);
150+
$this->assertEquals(42, $class_two->class_one->test_variable);
151+
}
152+
74153
}

0 commit comments

Comments
 (0)