Search code examples
routeslaravel-routinglaravel-6php-7.3

Optional routing params passed to controller


In Laravel 6.x, how do I get optional parameters to my controller? For example, my route:

Route::get('/videos/{limit?}/{channel?}, VideosController@index);

And in my VideosController I have a method:

public function index($limit=20, $channel=null)
{
   if (!is_null($channel))
   { 
      $channel_id = channel::where('name', $channel);
      $result = 
          <some complicated DB query>
          ->where('channel_id', $channel_id)
          ->limit($limit)
          ->first();
   } else {
      $result = 
          <some complicated DB query>
          ->limit($limit)
   }
}

But for some reason I never seem to fall into the !is_null($channel) case.


Solution

  • If the limit and channel are both optional url segments in your route, your application will not know that you intend to populate the channel variable if the limit is missing. It will mistake it for being the limit.

    What would be best in your case is to pass these as GET parameters, checking in your controller whether they have been populated.

    Firstly, change your route to exclude the optional parameters:

    Route::get('/videos', VideosController@index);
    

    Then in your controller:

    public function index()
    {
       if (request()->has('channel'))
       { 
          $channel_id = channel::where('name', request('channel'));
          $result = 
              <some complicated DB query>
              ->where('channel_id', $channel_id)
              ->limit(request('limit', 20))
              ->first();
       } else {
          $result = 
              <some complicated DB query>
              ->limit(request('limit', 20))
       }
    }
    

    Then, the query for example would be /videos?channel=example&limit=30.

    The request() helper allows a default value to be set if the parameter has been passed. Commonly you will see the request passed within the controller, so you can acheive the same thing with $request->query('limit', 20).

    I hope this helps.