From 8b84d293fb062f2316734bb0d1478e435cbfa49d Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Tue, 13 Dec 2016 21:17:26 -0500 Subject: [PATCH 1/3] Add support for binding Class@method callbacks --- src/Illuminate/Container/Container.php | 50 ++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index f3c10fe02a66..f57a77b8a786 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -36,6 +36,13 @@ class Container implements ArrayAccess, ContainerContract */ protected $bindings = []; + /** + * The container's method bindings. + * + * @var array + */ + protected $methodBindings = []; + /** * The container's shared instances. * @@ -232,6 +239,42 @@ protected function getClosure($abstract, $concrete) }; } + /** + * Bind a callback to resolve with Container::call + * + * @param string $method + * @param \Closure $concrete + * @return void + */ + public function bindMethod($method, $callback) + { + $this->methodBindings[$this->normalize($method)] = $callback; + } + + /** + * Call a method that has been bound to the container + * + * @param callable $callback + * @param mixed $default + * @return mixed + */ + protected function callBoundMethod($callback, $default) + { + if (!is_array($callback)) { + return value($default); + } + + $class = is_string($callback[0]) ? $callback[0] : get_class($callback[0]); + + $method = $this->normalize("{$class}@{$callback[1]}"); + + if (!isset($this->methodBindings[$method])) { + return value($default); + } + + return $this->methodBindings[$method]($callback[0], $this); + } + /** * Add a contextual binding to the container. * @@ -503,9 +546,10 @@ public function call($callback, array $parameters = [], $defaultMethod = null) return $this->callClass($callback, $parameters, $defaultMethod); } - $dependencies = $this->getMethodDependencies($callback, $parameters); - - return call_user_func_array($callback, $dependencies); + return $this->callBoundMethod($callback, function () use ($callback, $parameters) { + $dependencies = $this->getMethodDependencies($callback, $parameters); + return call_user_func_array($callback, $dependencies); + }); } /** From 45306f63049eaa6e49b695e6a162ceb8e72843f0 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Wed, 14 Dec 2016 09:23:38 -0500 Subject: [PATCH 2/3] Add tests for container method binding --- tests/Container/ContainerTest.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/Container/ContainerTest.php b/tests/Container/ContainerTest.php index d2403f207f69..af6e9fdddda9 100755 --- a/tests/Container/ContainerTest.php +++ b/tests/Container/ContainerTest.php @@ -509,6 +509,23 @@ public function testCallWithGlobalMethodName() $this->assertEquals('taylor', $result[1]); } + public function testCallWithBoundMethod() + { + $container = new Container; + $container->bindMethod('ContainerTestCallStub@unresolvable', function ($stub) { + return $stub->unresolvable('foo', 'bar'); + }); + $result = $container->call('ContainerTestCallStub@unresolvable'); + $this->assertEquals(['foo', 'bar'], $result); + + $container = new Container; + $container->bindMethod('ContainerTestCallStub@unresolvable', function ($stub) { + return $stub->unresolvable('foo', 'bar'); + }); + $result = $container->call([new ContainerTestCallStub, 'unresolvable']); + $this->assertEquals(['foo', 'bar'], $result); + } + public function testContainerCanInjectDifferentImplementationsDependingOnContext() { $container = new Container; @@ -812,6 +829,11 @@ public function inject(ContainerConcreteStub $stub, $default = 'taylor') { return func_get_args(); } + + public function unresolvable($foo, $bar) + { + return func_get_args(); + } } class ContainerTestContextInjectOne From a153c59ae7d9c254b2c17eb321066f6b4da32f33 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Wed, 14 Dec 2016 10:25:54 -0500 Subject: [PATCH 3/3] Apply Style CI fixes --- src/Illuminate/Container/Container.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Container/Container.php b/src/Illuminate/Container/Container.php index f57a77b8a786..c6d3a2ee1b4b 100755 --- a/src/Illuminate/Container/Container.php +++ b/src/Illuminate/Container/Container.php @@ -240,7 +240,7 @@ protected function getClosure($abstract, $concrete) } /** - * Bind a callback to resolve with Container::call + * Bind a callback to resolve with Container::call. * * @param string $method * @param \Closure $concrete @@ -252,7 +252,7 @@ public function bindMethod($method, $callback) } /** - * Call a method that has been bound to the container + * Call a method that has been bound to the container. * * @param callable $callback * @param mixed $default @@ -260,7 +260,7 @@ public function bindMethod($method, $callback) */ protected function callBoundMethod($callback, $default) { - if (!is_array($callback)) { + if (! is_array($callback)) { return value($default); } @@ -268,7 +268,7 @@ protected function callBoundMethod($callback, $default) $method = $this->normalize("{$class}@{$callback[1]}"); - if (!isset($this->methodBindings[$method])) { + if (! isset($this->methodBindings[$method])) { return value($default); } @@ -548,6 +548,7 @@ public function call($callback, array $parameters = [], $defaultMethod = null) return $this->callBoundMethod($callback, function () use ($callback, $parameters) { $dependencies = $this->getMethodDependencies($callback, $parameters); + return call_user_func_array($callback, $dependencies); }); }