2016-08-30 73 views
7

由于Laravel 5.3,路由隐式绑定的工作方式为中间件SubstituteBindings。我和Laravel 5.2一起工作,现在升级到5.3。Laravel 5.3 SubstituteBindings中间件with withoutMiddleware问题

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

我不知道这是否考虑为错误,但这对我来说是一个巨大的问题。 是否有任何方法将SubstituteBindings中间件设置为withoutMiddleware不会禁用的必需中间件?我如何仍然可以使用隐式绑定并在没有其他中间件的情况下测试我的测试?

+1

我也看到这一点,它基本上使测试不可能,因为我的应用程序严重依赖绑定。 Laravel GitHub存储库中存在一个问题(https:// github。com/laravel/framework/issues/15163),但似乎很快就没有讨论就把它当作一个非问题。我能想到的唯一'修复'是找到一种不使用'withoutMiddleware'或注册一个总是使用'SubstituteBindings'中间件的自定义路由器的方法。 – andyberry88

回答

1

基于我上面的评论建立了一个注册自定义路由器,如果中间件被禁用,它总是会将SubstituteBindings添加到中间件列表中。您可以通过注册自定义RoutingServiceProvider并注册您自己的Router课程来实现。不幸的是,由于该路线在应用程序引导过程中很早就已经创建,因此您还需要创建一个自定义App类并在bootstrap/app.php中使用该类。

RoutingServiceProvider

<?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); 
     }); 
    } 
} 

定制路由器

这增加了中间件,它只是扩展了默认的路由器,但覆盖runRouteWithinStack方法,而不是如果$this->container->make('middleware.disable')是真的返回一个空数组它会返回一个包含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) 
         ); 
        }); 
    } 
} 

自定义应用类

<?php namespace App; 

use App\Extensions\Providers\RoutingServiceProvider; 

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

使用自定义应用程序的类

bootstrap/app.php变化的线,其中该应用被实例化到:

$app = new App\MyCustomApp(
    realpath(__DIR__.'/../') 
); 

-

警告!我还没有完全测试这个,我的应用程序加载和我的测试通过,但可能有问题,我还没有发现。这也相当脆弱,因为如果Laravel基类Router类更改,您可能会发现事情在未来升级时随机突破。

-

您可能还需要重构自定义路由器这使中间件的名单总是包含SubstituteBindings类,所以没有那么多的行为差异,如果中间件被禁用。