90

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?
});

7 Answers 7

170

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

If one of the two parameters is sent, will it be set to $start since that was the first one defined in the route?
Always forget if the ? goes before or after the var. Tanks!
17

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

Comments

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.

3 Comments

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}, ...);
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.
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.
5
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

Comments

5

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');
    }
}

1 Comment

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.
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;

});

Comments

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");
}

1 Comment

@Michael Pittino's answer is the best practice way to do this

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.