From 8bb049a2e5cb84c5eb7d940c10b05aaf18f67c3d Mon Sep 17 00:00:00 2001 From: Erik Gaal Date: Wed, 24 Feb 2021 17:20:51 +0100 Subject: [PATCH 1/3] feat: respect route custom key for explicit route model bindings --- src/Illuminate/Routing/RouteBinding.php | 8 +++---- src/Illuminate/Routing/Router.php | 2 +- tests/Routing/RoutingRouteTest.php | 28 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Illuminate/Routing/RouteBinding.php b/src/Illuminate/Routing/RouteBinding.php index 133a84a40b07..45b2e8ec8d05 100644 --- a/src/Illuminate/Routing/RouteBinding.php +++ b/src/Illuminate/Routing/RouteBinding.php @@ -33,7 +33,7 @@ public static function forCallback($container, $binder) */ protected static function createClassBinding($container, $binding) { - return function ($value, $route) use ($container, $binding) { + return function ($value, $route, $key) use ($container, $binding) { // If the binding has an @ sign, we will assume it's being used to delimit // the class name from the bind method name. This allows for bindings // to run multiple bind methods in a single class for convenience. @@ -41,7 +41,7 @@ protected static function createClassBinding($container, $binding) $callable = [$container->make($class), $method]; - return $callable($value, $route); + return $callable($value, $route, $key); }; } @@ -57,7 +57,7 @@ protected static function createClassBinding($container, $binding) */ public static function forModel($container, $class, $callback = null) { - return function ($value) use ($container, $class, $callback) { + return function ($value, $route, $key) use ($container, $class, $callback) { if (is_null($value)) { return; } @@ -67,7 +67,7 @@ public static function forModel($container, $class, $callback = null) // throw a not found exception otherwise we will return the instance. $instance = $container->make($class); - if ($model = $instance->resolveRouteBinding($value)) { + if ($model = $instance->resolveRouteBinding($value, $route->bindingFieldFor($key))) { return $model; } diff --git a/src/Illuminate/Routing/Router.php b/src/Illuminate/Routing/Router.php index dfdb7ae7332e..4e57ffc6ec9d 100644 --- a/src/Illuminate/Routing/Router.php +++ b/src/Illuminate/Routing/Router.php @@ -840,7 +840,7 @@ public function substituteImplicitBindings($route) */ protected function performBinding($key, $value, $route) { - return call_user_func($this->binders[$key], $value, $route); + return call_user_func($this->binders[$key], $value, $route, $key); } /** diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index a0d4548dc06e..fb0d9c348a9e 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -3,6 +3,7 @@ namespace Illuminate\Tests\Routing; use Closure; +use Mockery; use DateTime; use Exception; use Illuminate\Auth\Middleware\Authenticate; @@ -938,6 +939,33 @@ public function testModelBinding() $this->assertSame('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); } + public function testModelBindingWithCustomKey() + { + // Create the router. + $container = new Container(); + $router = new Router(new Dispatcher(), $container); + $container->singleton(Registrar::class, function () use ($router) { + return $router; + }); + + $router->get('foo/{bar:custom}', ['middleware' => SubstituteBindings::class, 'uses' => function ($name) { + return $name; + }]); + $router->model('bar', RouteModelBindingStub::class); + + // Mock the stub so we can verify that the method is called with custom key. + $mock = $container->instance( + RouteModelBindingStub::class, + Mockery::mock(RouteModelBindingStub::class), + ); + + $mock->shouldReceive('resolveRouteBinding') + ->with('taylor', 'custom') + ->andReturn('TAYLOR'); + + $this->assertSame('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); + } + public function testModelBindingWithNullReturn() { $this->expectException(ModelNotFoundException::class); From e1854cd50886ef1778307dc47fda520ffbab4754 Mon Sep 17 00:00:00 2001 From: Erik Gaal Date: Wed, 24 Feb 2021 17:26:47 +0100 Subject: [PATCH 2/3] tests: close mockery after test --- tests/Routing/RoutingRouteTest.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index fb0d9c348a9e..0593b89730b9 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -961,9 +961,12 @@ public function testModelBindingWithCustomKey() $mock->shouldReceive('resolveRouteBinding') ->with('taylor', 'custom') + ->once() ->andReturn('TAYLOR'); $this->assertSame('TAYLOR', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent()); + + Mockery::close(); } public function testModelBindingWithNullReturn() From d5d9bc7f276a2f29d8e64703bf95881a141c3ecd Mon Sep 17 00:00:00 2001 From: Erik Gaal Date: Wed, 24 Feb 2021 17:34:33 +0100 Subject: [PATCH 3/3] style: changes from StyleCI --- tests/Routing/RoutingRouteTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Routing/RoutingRouteTest.php b/tests/Routing/RoutingRouteTest.php index 0593b89730b9..f4244a3bbb3e 100644 --- a/tests/Routing/RoutingRouteTest.php +++ b/tests/Routing/RoutingRouteTest.php @@ -3,7 +3,6 @@ namespace Illuminate\Tests\Routing; use Closure; -use Mockery; use DateTime; use Exception; use Illuminate\Auth\Middleware\Authenticate; @@ -30,6 +29,7 @@ use Illuminate\Routing\UrlGenerator; use Illuminate\Support\Str; use LogicException; +use Mockery; use PHPUnit\Framework\TestCase; use stdClass; use Symfony\Component\HttpFoundation\Response as SymfonyResponse;