Laravel 5.3 SubstituteBindings中间件,没有中间件问题

nro*_*fis 9 laravel laravel-5 laravel-5.3

从Laravel 5.3开始,路由隐式绑定就像中间件一样被称为SubstituteBindings.我和Laravel 5.2一起工作,现在升级到5.3.

我的应用程序中有自定义中间件,在我的测试中,我有时需要禁用它们.所以直到现在我才使用$this->withoutMiddleware()测试方法.但是自从更新到Laravel 5.3后,withoutMiddleware停止路由隐式绑定,并且我的所有测试都失败了.

我不知道这是否被视为错误,但对我来说这是一个很大的问题.有没有办法将SubstituteBindings中间件设置为withoutMiddleware不会禁用的强制中间件?如何在没有其他中间件的情况下仍然使用隐式绑定并测试我的测试?

and*_*y88 1

根据上面的评论,我查看了注册一个自定义路由器,SubstituteBindings如果中间件被禁用,它总是添加到中间件列表中。您可以通过注册自定义RoutingServiceProvider并注册您自己的Router类来实现它。不幸的是,由于路由是在应用程序引导过程中相当早创建的,因此您还需要创建一个自定义应用程序类并在其中使用它bootstrap/app.php

路由服务提供商

<?php namespace App\Extensions\Providers;

use Illuminate\Routing\RoutingServiceProvider as IlluminateRoutingServiceProvider;
use App\Extensions\ExtendedRouter;

class RoutingServiceProvider extends IlluminateRoutingServiceProvider
{
    protected function registerRouter()
    {
        $this->app['router'] = $this->app->share(function ($app) {
            return new ExtendedRouter($app['events'], $app);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

定制路由器

这添加了中间件,它只是扩展了默认路由器,但覆盖了该runRouteWithinStack方法,并且如果$this->container->make('middleware.disable')为 true,它不会返回空数组,而是返回一个包含该类的数组SubstituteBindings

<?php namespace App\Extensions;

use Illuminate\Routing\Router;
use Illuminate\Routing\Route;
use Illuminate\Routing\Pipeline;
use Illuminate\Http\Request;

class ExtendedRouter extends Router {

    protected function runRouteWithinStack(Route $route, Request $request)
    {
        $shouldSkipMiddleware = $this->container->bound('middleware.disable') &&
                                $this->container->make('middleware.disable') === true;

        // Make sure SubstituteBindings is always used as middleware
        $middleware = $shouldSkipMiddleware ? [
            \Illuminate\Routing\Middleware\SubstituteBindings::class
        ] : $this->gatherRouteMiddleware($route);

        return (new Pipeline($this->container))
                    ->send($request)
                    ->through($middleware)
                    ->then(function ($request) use ($route) {
                        return $this->prepareResponse(
                            $request, $route->run($request)
                        );
                    });
    }
}
Run Code Online (Sandbox Code Playgroud)

自定义应用程序类

<?php namespace App;

use App\Extensions\Providers\RoutingServiceProvider;

class MyCustomApp extends Application
{
    protected function registerBaseServiceProviders()
    {
        parent::registerBaseServiceProviders();
        $this->register(new RoutingServiceProvider($this));
    }
Run Code Online (Sandbox Code Playgroud)

使用自定义应用程序类

bootstrap/app.php实例化应用程序的行更改为:

$app = new App\MyCustomApp(
    realpath(__DIR__.'/../')
);
Run Code Online (Sandbox Code Playgroud)

--

警告!我还没有对此进行全面测试,我的应用程序已加载且测试通过,但可能存在我尚未发现的问题。它也很脆弱,因为如果 Laravel 基础Router类发生变化,您可能会发现在未来的升级中会随机损坏。

--

您可能还想重构它,以便自定义路由器中的中间件列表始终包含该类SubstituteBindings,因此如果禁用中间件,行为上不会有太大差异。