Search code examples
phplaravellaravel-5laravel-routing

Multiple route argument patterns in one route in Laravel 5.2


Hello,

for start, I really tried to google this. But it seems impossible to use a route argument pattern more than once in one route. My goal is an argument validation in route definition for routes like /resource/{uuid}/subresource/{uuid} without having to check those arguments manually in controller.

Let's assume we have:

$router->pattern('uuid', '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}');

Works perfectly for routes like

$router->get('/payment/{uuid}', 'Payments@payment');
$router->get('/users/{uuid}', 'Users@get');
//etc..

BUT

$router->get('/users/{uuid}/order/{uuid}', 'Controller@someStuff');

throws an error:

"Route pattern "/users/{uuid}/order/{uuid}" cannot reference variable name "uuid" more than once."

Seems legit. But I just want to validate arguments by regex DRY and other approaches like below does not work too:

$router->get('/users/{userId}/order/{orderId}', 'Controller@someStuff')
        ->where(['userId' => 'uuid', 'orderId' => 'uuid']); 
// or

$router->get('/users/{userId:uuid}/order/{orderId:uuid}', 'Controller@someStuff');

// ..and vice versa

Only thing that works is this:

$router->get('/users/{userId}/order/{orderId}', 'Controller@someStuff')
        ->where(['userId' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}', 'orderId' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}']);

... but I really don't wanna go through this way. That's actually the only way it worked.

Does anyone knows some trick, how to apply route argument pattern multiple times?

Thanks, any help would be appreciated...


Solution

  • Laravel doesn't seem to support named route patterns. I've had to deal with this sort of thing before and I've found this to be a reliable way of doing things:

    Open up RouterServiceProvider.php in app/Providers and add the following to your boot() method:

    /**
     * Define your route model bindings, pattern filters, etc.
     *
     * @param  \Illuminate\Routing\Router  $router
     * @return void
     */
    public function boot(Router $router)
    {
        $uuidPattern = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}';
    
        $router->pattern('userId', $uuidPattern);
        $router->pattern('orderId', $uuidPattern);
        $router->pattern('anotherUuid', $uuidPattern); // Just an example - delete this line!
    
        parent::boot($router);
    }
    

    Basically, you can add all your router patterns in there and they will be made available to your routes. They're all in one place so it's easy to remember where they are should you need update them and you can reuse the same pattern for multiple parameters.