Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting route parameters in Lumen

When trying to access Route parameters, using $request->route('id'), in latest version of Lumen, I get an error.

lumen.ERROR: Symfony\Component\Debug\Exception\FatalThrowableError: 
Call to a member function parameter() on array

It works fine in Laravel.

like image 695
Zoon Avatar asked Jan 21 '18 17:01

Zoon


People also ask

Should I use Lumen or Laravel?

Lumen is a micro framework, used to develop micro-services and API development in high speed and less time. Lumen declines the SQL queries cant perform tuining on databases, less featured compare to Laravel. Laravel is better for building RESTful APIs. Lumen is better for building high performing micro framework API.

What is Route parameter in Laravel?

Laravel routes are located in the app/Http/routes. php file. A route usually has the URL path, and a handler function callback, which is usually a function written in a certain controller.

Is Lumen and Laravel same?

Key Differences between Laravel vs Lumen Laravel is a full-stack web application framework that packages or supports a lot of third-party tools and frameworks, whereas Lumen is a micro-framework that is used to develop microservices and API development with the intent of providing speed and high response time.


2 Answers

Lumen is so stripped down, that the Route resolves to a simple array, rather than a Route object.

This is a problem, since the Request::route($key) method assumes the Route will have a parameter method.

But if you call Request::route(null), the complete Route array will be returned, looking something like this:

array(3) {
  [0]=>
  int(1)
  [1]=>
  array(2) {
    ["uses"]=>
    string(40) "App\Http\Controllers\SomeController@index"
    ["middleware"]=>
    array(2) {
      [0]=>
      string(4) "auth"
      [1]=>
      string(4) "example"
    }
  }
  [2]=>
  array(1) {
    ["id"]=>
    string(36) "32bd15fe-fec8-11e7-ac6b-e0accb7a6476"
  }
}

Where [2] always seems to contain the Route parameters.

I made a simple helper class to work with the Route parameters on Lumen. You can get, set and forget route parameters. This is works great if you need to manipulate them in your middleware.

Save in app/Support/RouteParam.php: https://gist.github.com/westphalen/c3cd187007e0448bcb7fca1de091e4df

And simply use it like this: $id = RouteParam::get($request, 'id');

Blame illuminate/http/Request.php:

/**
 * Get the route handling the request.
 *
 * @param  string|null  $param
 *
 * @return \Illuminate\Routing\Route|object|string
 */
public function route($param = null)
{
    $route = call_user_func($this->getRouteResolver());

    if (is_null($route) || is_null($param)) {
        return $route;
    }

    return $route->parameter($param); // can't call parameter on array.
}
like image 79
Zoon Avatar answered Oct 10 '22 12:10

Zoon


The problem is Lumen just is not yet registers route information in the global middleware.

So, you'll just get empty string if you call $request->route():

class MyMiddleware {
    public function handle($request, Closure $next)
    {
        $request->route(); // empty string or null
        return $next($request);
    }
}

The decision is to define your middleware as a route middleware and manually set it to each needed route. bootstrap/app.php:

$app->middleware([
//    MyMiddleware::class, // do not use global middleware
]);

$app->routeMiddleware([
    MyMiddleware::class,
]);


// And then apply the middleware to every route using a group:
$app->router->group([
    'namespace' => 'App\Http\Controllers',
    'middleware' => [MyMiddleware::class],
], function ($router) {
    require __DIR__ . '/../routes/web.php';
});

The final correct middleware:

class MyMiddleware
{
    public function handle($request, Closure $next)
    {
        // @see https://github.com/laravel/lumen-framework/issues/119#issuecomment-298835011
        $route = $request->route();
        $routeParameters = is_array($route) ? $route[2] : $route->parameters();
     
        return $next($request);
    }
}

like image 33
James Bond Avatar answered Oct 10 '22 12:10

James Bond