Laravel 5.3 промежуточное ПО SubstituteBindings с проблемой withoutMiddleware

начиная с Laravel 5.3, неявная привязка маршрута работает как промежуточное ПО SubstituteBindings. Я работал с Laravel 5.2 и 5.3 сейчас.

у меня есть пользовательские middlewares в моем приложении, и в моих тестах мне иногда нужно отключить их. Поэтому до сих пор я использовал $this->withoutMiddleware() методы испытаний. Но с момента обновления до Laravel 5.3,withoutMiddleware останавливает неявную привязку маршрута, и все мои тесты терпят неудачу.

Я не знаю, если это считать ошибкой, но это огромная проблема для меня. Есть ли способ установить SubstituteBindings middleware как обязательное промежуточное ПО, которое withoutMiddleware не отключить? Как я могу использовать неявную привязку и тестировать свои тесты без других промежуточных программ?

1 ответов


основываясь на моем комментарии выше, я посмотрел на регистрацию пользовательского маршрутизатора, который всегда добавляет SubstituteBindings в список промежуточного ПО, если промежуточное ПО было отключено. Вы можете достичь этого, зарегистрировав custom RoutingServiceProvider и зарегистрировать свой собственный Router класса. К сожалению, поскольку маршрут создается довольно рано в процессе начальной загрузки приложения, вам также нужно создать пользовательский класс приложения и использовать его в 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));
    }

С помощью специального приложения класс!--18-->

на bootstrap/app.php измените строку, в которой экземпляр приложения:

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

--

предупреждение! я не полностью протестировал это, мое приложение загружается и мои тесты проходят, но могут быть проблемы, которые я не обнаружил. Он также довольно хрупкий, так как если база Laravel Router изменения класса вы можете найти вещи ломаются случайным образом на будущих обновлениях.

--

возможно, вы также хотите, чтобы рефакторинг это так список промежуточного ПО в пользовательском маршрутизаторе всегда содержит SubstituteBindings класс, поэтому нет большой разницы в поведении, если промежуточное ПО отключено.