4

I am having a hard time accessing the Route URL Parameter in Middleware after updating from Laravel 5.1 to Laravel 5.3.

Here is my route file:

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 has RouteMiddleware updated like this:

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,
    ];

In Laravel 5.1 and I was able to access route parameter from middleware like this and I had no trouble:

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

But, since upgrading to Laravel 5.3, the above code started returned $appId as null. I also tried accessing route parameter like $appId = $request->apps and this was not working as well.

So I then changed the Middleware to get the url parameter like this:

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

Since changing to the above, the middleware seems to be working for the first route. But then, I am having problem when going to the second route that has 2 parameters. For some reason, the above code fails and when returning $request->route()->parameters('apps') from middleware, I am getting an array like this:

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

Why is that? Why is it not returning just the $appId which is 1? Am I missing something or is it a bug in Laravel 5.3? I want the Middleware to access only the appId parameter from the url and nothing else from the route. Can someone help me here please?

Update 1:

I tried changing the Middleware to get parameter like this:

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

In the above, I am getting the error:

Undefined index: apps

But when I print_r($parameters);, the output is like this:

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

Solution:

In the end, I found out the reason for this odd behaviour was due the parameter name in the url.

The following resources routes were generating route url parameter as app instead of apps. I dont know why though:

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

Whereas the following routes were generating route url parameter as apps:

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

Due to this odd behaviour, some routes were returning null for the parameter name apps and some where showing the parameter. Once I renamed all route parameters to {app} in the routes/api.php and Middleware, the Middleware started working the way it should.

I don't know why the resource routes were creating the parameter as app, but the above fixed the error for me, atleast for now.

Neel
  • 9,352
  • 23
  • 87
  • 128
  • The route() method should work in the middleware Laravel 5.3 to get a route param. Works fine for me. – schellingerht Oct 24 '16 at 19:23
  • @schellingerht For me the `route()` method is always returning as null in Laravel 5.3. I have already added the middleware to `RouteMiddleware` in `Kernel.php` and its still null. I understand that Laravel 5.3 has changed the route file to api and web and the middleware I am using is for the api group, does that change anything? I dont understand why `route()` in middleware is showing null after updating. – Neel Oct 25 '16 at 09:40

3 Answers3

3

There are two ways for accessing parameters in a middleware:

Method 1 $request->route('parameter_name'); Here parameter_name refers to what we called the parameter in the route.

Method 2 $request->route()->parameters(); This method will return an array of all the parameters.

Amit Gupta
  • 17,072
  • 4
  • 41
  • 53
  • When I tried the Method 1, I am getting it as null. In method 2, I only want to get the `appId` so when I add it as `$request->route()->parameters('apps')`, I am still getting the array of all parameters when the url has multiple parameter like the example in my OP. – Neel Oct 25 '16 at 09:44
  • For Method 1 - Make sure you are using the same name for `parameter_name` for what you called it in route.php. As for `Route::get('apps/{apps}/houses/colour/{colour}', 'HouseController@colourCheck');` you will call it as `$request->route('apps')` or `$request->route('colour')`. And `$request->route()->parameters();` doesn't accecpt any parameters, it always returns an array. – Amit Gupta Oct 25 '16 at 10:00
  • Thanks for your reply @AmitGupta I did use the `route()` method as `$request->route('apps')`, but it is returning as `null`. `apps` is the parameter name called in `routes/api.php`. I have also added the middleware to `RouteMiddleware` in `Kernel.php` but still its returned as null. – Neel Oct 25 '16 at 10:04
  • I tried the second method to get the `appId` parameter from the array but that is not working neither. I have updated my post with what I tried and what output I am getting when I use `print_r`. – Neel Oct 25 '16 at 10:26
  • Have updating my post with the solution that worked for now. Thanks for your answer. – Neel Oct 26 '16 at 07:41
1

Resource Parameters Are Singular By Default

If you would like to maintain the previous behavior instead of automatically singularizing resource route parameters, you may make the following call to the singularResourceParameters method in your AppServiceProvider:

use Illuminate\Support\Facades\Route;

Route::singularResourceParameters(false);
Harry Bosh
  • 3,611
  • 2
  • 36
  • 34
  • ah... thanks @HarryBosh for the link. Now it makes sense on why the route parameter is singularised in 5.3 only. – Neel Nov 11 '16 at 18:18
0

For me, this was the solution for Laravel 6.

In the routes file add ->middleware() like this:

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

Now to retrieve the parameters in the middleware class:

public function handle($request, Closure $next, ...$roles)
{
     // now $roles contains: ['Admin, 'System']
}
Floris
  • 2,727
  • 2
  • 27
  • 47