Skip to content

Commit 15c1ddd

Browse files
committed
Merge branch 'route-else' into 8.x
2 parents 05da44d + 0a5face commit 15c1ddd

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

src/Illuminate/Routing/Middleware/SubstituteBindings.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Closure;
66
use Illuminate\Contracts\Routing\Registrar;
7+
use Illuminate\Database\Eloquent\ModelNotFoundException;
78

89
class SubstituteBindings
910
{
@@ -34,9 +35,17 @@ public function __construct(Registrar $router)
3435
*/
3536
public function handle($request, Closure $next)
3637
{
37-
$this->router->substituteBindings($route = $request->route());
38+
try {
39+
$this->router->substituteBindings($route = $request->route());
3840

39-
$this->router->substituteImplicitBindings($route);
41+
$this->router->substituteImplicitBindings($route);
42+
} catch (ModelNotFoundException $exception) {
43+
if ($route->getMissing()) {
44+
return $route->getMissing()($request);
45+
}
46+
47+
throw $exception;
48+
}
4049

4150
return $next($request);
4251
}

src/Illuminate/Routing/Route.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,34 @@ public function setAction(array $action)
933933
return $this;
934934
}
935935

936+
/**
937+
* Get the value of the action that should be taken on a missing model exception.
938+
*
939+
* @return \Closure|null
940+
*/
941+
public function getMissing()
942+
{
943+
$missing = $this->action['missing'] ?? null;
944+
945+
return is_string($missing) &&
946+
Str::startsWith($missing, 'C:32:"Opis\\Closure\\SerializableClosure')
947+
? unserialize($missing)
948+
: $missing;
949+
}
950+
951+
/**
952+
* Define the callable that should be invoked on a missing model exception.
953+
*
954+
* @param \Closure $missing
955+
* @return $this
956+
*/
957+
public function missing($missing)
958+
{
959+
$this->action['missing'] = $missing;
960+
961+
return $this;
962+
}
963+
936964
/**
937965
* Get all middleware, including the ones from the controller.
938966
*
@@ -1167,8 +1195,10 @@ public function prepareForSerialization()
11671195
{
11681196
if ($this->action['uses'] instanceof Closure) {
11691197
$this->action['uses'] = serialize(new SerializableClosure($this->action['uses']));
1198+
}
11701199

1171-
// throw new LogicException("Unable to prepare route [{$this->uri}] for serialization. Uses Closure.");
1200+
if (isset($this->action['missing']) && $this->action['missing'] instanceof Closure) {
1201+
$this->action['missing'] = serialize(new SerializableClosure($this->action['missing']));
11721202
}
11731203

11741204
$this->compileRoute();

tests/Routing/RoutingRouteTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Illuminate\Events\Dispatcher;
1616
use Illuminate\Http\Exceptions\HttpResponseException;
1717
use Illuminate\Http\JsonResponse;
18+
use Illuminate\Http\RedirectResponse;
1819
use Illuminate\Http\Request;
1920
use Illuminate\Http\Response;
2021
use Illuminate\Routing\Controller;
@@ -1671,6 +1672,27 @@ public function testImplicitBindingsWithOptionalParameterWithExistingKeyInUri()
16711672
$this->assertSame('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
16721673
}
16731674

1675+
public function testImplicitBindingsWithMissingModelHandledByMissing()
1676+
{
1677+
$router = $this->getRouter();
1678+
$router->get('foo/{bar}', [
1679+
'middleware' => SubstituteBindings::class,
1680+
'uses' => function (RouteModelBindingNullStub $bar = null) {
1681+
$this->assertInstanceOf(RouteModelBindingNullStub::class, $bar);
1682+
1683+
return $bar->first();
1684+
},
1685+
])->missing(function () {
1686+
return new RedirectResponse('/', 302);
1687+
});
1688+
1689+
$request = Request::create('foo/taylor', 'GET');
1690+
1691+
$response = $router->dispatch($request);
1692+
$this->assertTrue($response->isRedirect('/'));
1693+
$this->assertEquals(302, $response->getStatusCode());
1694+
}
1695+
16741696
public function testImplicitBindingsWithOptionalParameterWithNoKeyInUri()
16751697
{
16761698
$router = $this->getRouter();

0 commit comments

Comments
 (0)