Skip to content

Commit

Permalink
[5.4] Make with (#18271)
Browse files Browse the repository at this point in the history
* Allow old container->make style functionality.

* Apply fixes from StyleCI (#18270)

* add broken test

* make all tests pass

* simplify calls

* add comment

* add comment

* add test and remove calls to last

* Apply fixes from StyleCI (#18274)
  • Loading branch information
taylorotwell authored Mar 13, 2017
1 parent e37b95f commit 5d9b363
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 2 deletions.
73 changes: 71 additions & 2 deletions src/Illuminate/Container/Container.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ class Container implements ArrayAccess, ContainerContract
*/
protected $buildStack = [];

/**
* The parameter override stack.
*
* @var array
*/
protected $with = [];

/**
* The contextual binding map.
*
Expand Down Expand Up @@ -537,6 +544,18 @@ public function factory($abstract)
};
}

/**
* Resolve the given type with the given parameter overrides.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
public function makeWith($abstract, array $parameters)
{
return $this->resolve($abstract, $parameters);
}

/**
* Resolve the given type from the container.
*
Expand All @@ -545,7 +564,21 @@ public function factory($abstract)
*/
public function make($abstract)
{
$needsContextualBuild = ! is_null(
return $this->resolve($abstract);
}

/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
protected function resolve($abstract, $parameters = [])
{
$this->with[] = $parameters;

$needsContextualBuild = ! empty($parameters) || ! is_null(
$this->getContextualConcrete($abstract = $this->getAlias($abstract))
);

Expand Down Expand Up @@ -583,8 +616,13 @@ public function make($abstract)

$this->fireResolvingCallbacks($abstract, $object);

// Before returning, we will also set the resolved flag to "true" and pop off
// the parameter overrides for this build. After those two things are done
// we will be ready to return back the fully constructed class instance.
$this->resolved[$abstract] = true;

array_pop($this->with);

return $object;
}

Expand Down Expand Up @@ -675,7 +713,7 @@ public function build($concrete)
// hand back the results of the functions, which allows functions to be
// used as resolvers for more fine-tuned resolution of these objects.
if ($concrete instanceof Closure) {
return $concrete($this);
return $concrete($this, end($this->with));
}

$reflector = new ReflectionClass($concrete);
Expand Down Expand Up @@ -725,6 +763,15 @@ protected function resolveDependencies(array $dependencies)
$results = [];

foreach ($dependencies as $dependency) {
// If this dependency has a override for this particular build we will use
// that instead as the value. Otherwise, we will continue with this run
// of resolutions and let reflection attempt to determine the result.
if ($this->hasParameterOverride($dependency)) {
$results[] = $this->getParameterOverride($dependency);

continue;
}

// If the class is null, it means the dependency is a string or some other
// primitive type which we can not resolve since it is not a class and
// we will just bomb out with an error since we have no-where to go.
Expand All @@ -736,6 +783,28 @@ protected function resolveDependencies(array $dependencies)
return $results;
}

/**
* Determine if the given dependency has a parameter override from makeWith.
*
* @param \ReflectionParameter $dependency
* @return bool
*/
protected function hasParameterOverride($dependency)
{
return array_key_exists($dependency->name, end($this->with));
}

/**
* Get a parameter override for a dependency.
*
* @param \ReflectionParameter $dependency
* @return mixed
*/
protected function getParameterOverride($dependency)
{
return end($this->with)[$dependency->name];
}

/**
* Resolve a non-class hinted primitive dependency.
*
Expand Down
56 changes: 56 additions & 0 deletions tests/Container/ContainerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,62 @@ public function testResolvingCallbacksShouldBeFiredWhenCalledWithAliases()

$this->assertEquals('taylor', $instance->name);
}

public function testResolvingWithArrayOfParameters()
{
$container = new Container;
$instance = $container->makeWith(ContainerDefaultValueStub::class, ['default' => 'adam']);
$this->assertEquals('adam', $instance->default);

$instance = $container->make(ContainerDefaultValueStub::class);
$this->assertEquals('taylor', $instance->default);

$container->bind('foo', function ($app, $config) {
return $config;
});

$this->assertEquals([1, 2, 3], $container->makeWith('foo', [1, 2, 3]));
}

public function testNestedParameterOverride()
{
$container = new Container;
$container->bind('foo', function ($app, $config) {
return $app->makeWith('bar', ['name' => 'Taylor']);
});
$container->bind('bar', function ($app, $config) {
return $config;
});

$this->assertEquals(['name' => 'Taylor'], $container->make('foo', ['something']));
}

public function testNestedParametersAreResetForFreshMake()
{
$container = new Container;

$container->bind('foo', function ($app, $config) {
return $app->make('bar');
});

$container->bind('bar', function ($app, $config) {
return $config;
});

$this->assertEquals([], $container->makeWith('foo', ['something']));
}

public function testSingletonBindingsNotRespectedWithMakeParameters()
{
$container = new Container;

$container->singleton('foo', function ($app, $config) {
return $config;
});

$this->assertEquals(['name' => 'taylor'], $container->makeWith('foo', ['name' => 'taylor']));
$this->assertEquals(['name' => 'abigail'], $container->makeWith('foo', ['name' => 'abigail']));
}
}

class ContainerConcreteStub
Expand Down

0 comments on commit 5d9b363

Please sign in to comment.