Доступ к параметру URL-адреса маршрута в промежуточном программном обеспечении в Laravel 5.3

Мне трудно получить доступ к параметру URL-адреса маршрута в промежуточном программном обеспечении после обновления с Laravel 5.1 до Laravel 5.3.

Вот мой файл маршрута:

Route::group(['middleware' => ['app.access']], function()
{
    Route::resource('apps/{apps}/houses', 'HouseController',
                    ['except' => ['index', 'create', 'edit']]);

    Route::get('apps/{apps}/houses/colour/{colour}', 'HouseController@colourCheck');
    ...
}

В Kernel.php RouteMiddleware обновляется следующим образом:

protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        // Added ones....
        'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class,
        'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class,
        // Custom Middleware
        'app.access' => \App\Http\Middleware\AppAccess::class,
    ];

В Laravel 5.1 я мог получить доступ к параметру маршрута из промежуточного программного обеспечения, как это, и у меня не было проблем:

public function handle($request, Closure $next)
{
        $appId = $request->route('apps');
        ...
}

Но после обновления до Laravel 5.3 приведенный выше код начал возвращать $appId как null. Я также попытался получить доступ к параметру маршрута, например $appId = $request->apps, и это тоже не сработало.

Затем я изменил промежуточное ПО, чтобы получить параметр url следующим образом:

public function handle($request, Closure $next)
{
        $appId = $request->route()->parameters('apps');
        ...
}

После перехода на вышеуказанное промежуточное программное обеспечение, похоже, работает для первого маршрута. Но тогда у меня проблема при переходе на второй маршрут с двумя параметрами. По какой-то причине приведенный выше код не работает, и при возврате $request->route()->parameters('apps') из промежуточного программного обеспечения я получаю такой массив:

Array
(
    [apps] => 1
    [colour] => green
)

Это почему? Почему он не возвращает только $appId, который равен 1? Я что-то упускаю или это ошибка в Laravel 5.3? Я хочу, чтобы промежуточное ПО получало доступ только к параметру appId из URL-адреса и ни к чему другому из маршрута. Может кто-нибудь помочь мне здесь, пожалуйста?

Обновление 1:

Я попытался изменить промежуточное ПО, чтобы получить такой параметр:

$parameters = $request->route()->parameters();
$appId = $parameters['apps'];

Выше я получаю сообщение об ошибке:

Undefined index: apps

Но когда я print_r($parameters);, результат будет таким:

Array
(
    [apps] => 1
    [day] => tuesday
)
[]

Решение:

В конце концов, я выяснил, что причина такого странного поведения связана с именем параметра в URL-адресе.

Следующие маршруты ресурсов генерировали параметр URL-адреса маршрута как app вместо apps. Я не знаю почему:

Route::resource('apps/{apps}/houses', 'HouseController',
                        ['except' => ['index', 'create', 'edit']]);

В то время как следующие маршруты генерировали параметр url маршрута как apps:

Route::get('apps/{apps}/houses/colour/{colour}', 'HouseController@colourCheck');

Из-за этого странного поведения некоторые маршруты возвращали null для имени параметра apps, а некоторые показывали параметр. После того, как я переименовал все параметры маршрута в {app} в routes/api.php и промежуточном программном обеспечении, промежуточное ПО начало работать так, как должно.

Я не знаю, почему маршруты ресурсов создавали параметр как app, но приведенное выше исправило ошибку для меня, по крайней мере, на данный момент.


person Neel    schedule 24.10.2016    source источник
comment
Метод route () должен работать в промежуточном программном обеспечении Laravel 5.3, чтобы получить параметр маршрута. У меня отлично работает.   -  person schellingerht    schedule 24.10.2016
comment
@schellingerht Для меня метод route() всегда возвращается как null в Laravel 5.3. Я уже добавил промежуточное ПО в RouteMiddleware в Kernel.php, и оно по-прежнему равно нулю. Я понимаю, что Laravel 5.3 изменил файл маршрута на api и web, а промежуточное ПО, которое я использую, предназначено для группы api, это что-то меняет? Я не понимаю, почему route() в промежуточном программном обеспечении показывает null после обновления.   -  person Neel    schedule 25.10.2016


Ответы (3)


Есть два способа доступа к параметрам в промежуточном программном обеспечении:

Метод 1 $request->route('parameter_name'); Здесь parameter_name относится к тому, что мы назвали параметром в маршруте.

Метод 2 $request->route()->parameters(); Этот метод возвращает массив всех параметров.

person Amit Gupta    schedule 25.10.2016
comment
Когда я попробовал метод 1, я получил его как null. В методе 2 я хочу получить только appId, поэтому, когда я добавляю его как $request->route()->parameters('apps'), я все равно получаю массив всех параметров, когда URL-адрес имеет несколько параметров, как в примере в моем OP. - person Neel; 25.10.2016
comment
Для метода 1 - убедитесь, что вы используете то же имя для parameter_name, которое вы назвали в route.php. Что касается Route::get('apps/{apps}/houses/colour/{colour}', 'HouseController@colourCheck');, вы назовете его как $request->route('apps') или $request->route('colour'). И $request->route()->parameters(); не принимает никаких параметров, он всегда возвращает массив. - person Amit Gupta; 25.10.2016
comment
Спасибо за ответ @AmitGupta. Я использовал метод route() как $request->route('apps'), но он возвращается как null. apps - это имя параметра, вызываемое в routes/api.php. Я также добавил промежуточное ПО в RouteMiddleware в Kernel.php, но оно все равно возвращается как null. - person Neel; 25.10.2016
comment
Я попробовал второй способ получить параметр appId из массива, но он тоже не работает. Я обновил свой пост, указав, что я пробовал, и какие результаты получаются при использовании print_r. - person Neel; 25.10.2016
comment
Обновите мой пост решением, которое работает на данный момент. Спасибо за Ваш ответ. - person Neel; 26.10.2016

Параметры ресурса по умолчанию единичны

Если вы хотите сохранить предыдущее поведение вместо автоматической сингулярности параметров маршрута ресурса, вы можете сделать следующий вызов метода singularResourceParameters в вашем AppServiceProvider:

use Illuminate\Support\Facades\Route;

Route::singularResourceParameters(false);
person Harry Bosh    schedule 09.11.2016
comment
ах ... спасибо @HarryBosh за ссылку. Теперь понятно, почему параметр маршрута выделен только в версии 5.3. - person Neel; 11.11.2016

Для меня это было решение для Laravel 6.

В файле маршрутов добавьте ->middleware() вот так:

Route::resource('orders', 'OrdersController')->middleware('roles:Admin,System');

Теперь, чтобы получить параметры в классе промежуточного программного обеспечения:

public function handle($request, Closure $next, ...$roles)
{
     // now $roles contains: ['Admin, 'System']
}
person Floris    schedule 17.02.2020