Laravel/Lumen manipulating Route Parameters

Syed Sirajul Islam Anik
3 min readMar 19, 2019

--

Image result for laravel love
https://cdn-images-1.medium.com/max/1200/1*IQ9laxKlEm6CodFOZIbgLQ.png

Assume you have defined routes like below,

// Laravel
Route::get('orders/{orderId}, 'OrderController@show')
->where('orderId', '\d+');
// Lumen
$router->get('order/{orderId:\d+}, 'OrderController@show');

And, the controller looks like below,

<?php namespace App\Http\Controllers;// ...class OrderController extends Controller
{
public function show(Request $request, $orderId) {
return Order::findOrFail($id);
}
}

So, the routes are straight forward. The URLs will have an integer id which represents the orderId and those will be passed to your controllers. You use that variable and perform actions. It’s quite common that you may use the Database table’s autoincrement id to communicate from clients to your server.

But, assume you now need to change those orderId variables from integer to your new super duper encrypted value so that no one can guess the order id.

So, you need to update the endpoints from \d+ to something else, if they are no more an integer. Even if they are an integer, they don’t serve the purpose like before. They are no more tables' primary key id. So, you may think to manipulate the controller’s orderId variable to something new that suits the new encrypted key.

WRONG! WHY?

Assume you have 10 routes which had that $orderId. Now, you need to change in all those places.

Be lazy!! Think in a different way.

Again! Middleware can be the savior. So, All you need to do is to create a middleware which will take those encrypted parameters, convert it to the actual order id and pass it to the controller.

For Laravel, you can do the following.

// EncryptedToRegularOrderIdMiddleware.php
...
public function handle($request, Closure $next) {
$encryptedOrderId = $request->route('orderId');
$request->route()->setParameter('orderId', (new Decoder())->decode($encryptedOrderId));
}

Now in your controller, you don’t have to change anything. Your controller won’t need an update as you changed the route parameter. You need to register the middleware and apply those to your routes.

Route::get('orders/{orderId}, [
'uses' => 'OrderController@show',
'middleware' => 'encryption_to_regular', // registered MW name.
])->where('orderId', '\d+');

Why did you mention Laravel in bold text?

Because in your middleware, in Laravel $request->route() returns Illuminate\Routing\Route object. In Lumen it’s not the same, it returns an array instead. So, you cannot just set the route Parameter there. You’ll get an exception raised. To achieve so, you need to register a routeResolver to your $request object which is a closure. So, the Middleware Class in Lumen looks like below,

// EncryptedToRegularOrderIdMiddleware.php
...
public function handle($request, Closure $next) {
$route = $request->route();
if (isset($route[2]['orderId'])) {
$route[2]['orderId'] = (new Decoder())->decode($orderId);
$request->setRouteResolver(function () use ($route) {
return $route;
});
}
}

In Lumen, $request->route() returns an array in which array key [2] holds the parameters that will be passed to the controller. You modify that value as we did for Laravel and finally register a closure usingsetRouteResolver. Now, this resolver will be used when passing data to your controller. Easy peasy. 😉

That’s it. Be lazy. Happy coding! ❤ 😎

--

--

Syed Sirajul Islam Anik

software engineer with "Senior" tag | procrastinator | programmer | !polyglot | What else 🙄 — Open to Remote