80

I'd like to create a route that takes a required ID, and optional start and end dates ('Ymd'). If dates are omitted, they fall back to a default. (Say last 30 days) and call a controller....lets say 'path@index'

Route::get('/path/{id}/{start?}/{end?}', function($id, $start=null, $end=null)
{
    if(!$start)
    {
        //set start
    }
    if(!$end)
    {
        //set end
    }
    
    // What is the syntax that goes here to call 'path@index' with $id, $start, and $end?
});
starball
  • 20,030
  • 7
  • 43
  • 238
Steve
  • 801
  • 1
  • 6
  • 3

7 Answers7

155

There is no way to call a controller from a Route:::get closure.

Use:

Route::get('/path/{id}/{start?}/{end?}', 'Controller@index');

and handle the parameters in the controller function:

public function index($id, $start = null, $end = null)
{
    if (!$start) {
        // set start
    }
        
    if (!$end) {
        // set end
    }
        
    // do other stuff
}
Mostafa Norzade
  • 1,578
  • 5
  • 24
  • 40
Michael Pittino
  • 2,040
  • 1
  • 10
  • 14
14

This helped me simplify the optional routes parameters (From Laravel Docs):

Occasionally you may need to specify a route parameter, but make the presence of that route parameter optional. You may do so by placing a ? mark after the parameter name. Make sure to give the route's corresponding variable a default value:

Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

Or if you have a controller call action in your routes then you could do this:

web.php

Route::get('user/{name?}', 'UsersController@index')->name('user.index');


userscontroller.php

public function index($name = 'John') {

  // Do something here

}

I hope this helps someone simplify the optional parameters as it did me!

Laravel 5.6 Routing Parameters - Optional parameters

OlaJ
  • 608
  • 7
  • 15
6

I would handle it with three paths:

Route::get('/path/{id}/{start}/{end}, ...);

Route::get('/path/{id}/{start}, ...);

Route::get('/path/{id}, ...);

Note the order - you want the full path checked first.

Yoram de Langen
  • 5,391
  • 3
  • 24
  • 31
Lea de Groot
  • 309
  • 4
  • 12
  • The only issue here would be this case: Route::get('/path/{id}/{end}, ...); Since you already have this route defined: Route::get('/path/{id}/{start}, ...); – mushood badulla Aug 03 '18 at 07:09
  • 3
    Interesting, but functionally, if only one date is provided, the code will have no way of knowing if that is an end or start date. The programmer will have to make a decision on which it should be. – Lea de Groot Aug 04 '18 at 08:35
  • You are absolutely correct. :) I read a little more about this and understood when they are multiple optional parameters, you always need to set the preceding parameter for the following parameters to be taken into account. That effectively makes your three routes correct. – mushood badulla Aug 06 '18 at 15:23
4
Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Find more details here (Laravel 7) : https://laravel.com/docs/7.x/routing#parameters-optional-parameters

Hicham O-Sfh
  • 731
  • 10
  • 12
1

You can call a controller action from a route closure like this:

Route::get('{slug}', function ($slug, Request $request) {

    $app = app();
    $locale = $app->getLocale();

    // search for an offer with the given slug
    $offer = \App\Offer::whereTranslation('slug', $slug, $locale)->first();
    if($offer) {
        $controller = $app->make(\App\Http\Controllers\OfferController::class);
        return $controller->callAction('show', [$offer, $campaign = NULL]);
    } else {
        // if no offer is found, search for a campaign with the given slug
        $campaign = \App\Campaign::whereTranslation('slug', $slug, $locale)->first();
        if($campaign) {
            $controller = $app->make(\App\Http\Controllers\CampaignController::class);
            return $controller->callAction('show', [$campaign]);
        }
    }

    throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

});
Alex
  • 12,205
  • 7
  • 42
  • 52
1

What I did was set the optional parameters as query parameters like so:

Example URL: /getStuff/2019-08-27?type=0&color=red

Route: Route::get('/getStuff/{date}','Stuff\StuffController@getStuff');

Controller:

public function getStuff($date)
{
        // Optional parameters
        $type = Input::get("type");
        $color = Input::get("color");
}
Cutedu
  • 139
  • 1
  • 3
1

Solution to your problem without much changes

Route::get('/path/{id}/{start?}/{end?}', function($id, $start=null, $end=null)
{
    if(empty($start))
    {
        $start = Carbon::now()->subDays(30)->format('Y-m-d');
    }
    if(empty($end))
    {
        $end = Carbon::now()->subDays(30)->format('Y-m-d');
    }
    return App\Http\Controllers\HomeController::Path($id,$start,$end);
});

and then

class HomeController extends Controller
{
public static function Path($id, $start, $end)
    {
        return view('view');
    }
}

now the optimal approach is

use App\Http\Controllers\HomeController;
Route::get('/path/{id}/{start?}/{end?}', [HomeController::class, 'Path']);

then

class HomeController extends Controller
{
    public function Path(Request $request)
    {
        if(empty($start))
        {
            $start = Carbon::now()->subDays(30)->format('Y-m-d');
        }
        if(empty($end))
        {
            $end = Carbon::now()->subDays(30)->format('Y-m-d');
        }
        //your code
        
        return view('view');
    }
}
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community May 09 '22 at 00:34