2016-08-30 104 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類,所以沒有那麼多的行爲差異,如果中間件被禁用。