Lazlo
Lazlo

Reputation: 8770

Is it possible to reorder or ignore parameters in controller routes?

The question title is the most explicit I could think of, but here's a use case/example for clarity's sake:

Say I define the following route to show an article:

Route::get('article/{slug}/{id}', 'ArticleController@show');

...

class ArticleController extends BaseController {

    public function show($id)
    {
        return View::make('article')->with('article', Article::find($id));
    }

}

This won't work, as show will misake the $id parameter with the $slug parameter. Is there a way to pass only the $id parameter to the show method?

Upvotes: 4

Views: 4469

Answers (3)

Torgheh
Torgheh

Reputation: 786

I dont know if you still look for solution or not, but as I had the same problem and I didn't like these solutions, I did this:

in the your ArticleController you overload the callAction($method, $parameters) method, this is a method in Laravel controller class, so it looks like this:

public function callAction($method, $parameters)
{
        unset($parameters['id']);
        unset($parameters['slug']);

        return parent::callAction($method, $parameters);
}

after this you ca easily do this:

public function show($id)
{
    return View::make('article')->with('article', Article::find($id));
}

Upvotes: 10

Lazlo
Lazlo

Reputation: 8770

It's possible to manually call controller functions:

Route::get('article/{slug}/{id}', function($slug, $id)
{
    return App::make('ArticleController')->show($id);
});

Upvotes: 5

Tomas Buteler
Tomas Buteler

Reputation: 4117

You can certainly "ignore" parameters with Laravel -- i.e. make them optional -- by adding a question mark after their name:

Route::get('article/{slug?}/{id?}', 'ArticleController@show');

Note that you are limited by PHPs way of handling optional function arguments: the leftmost arguments cannot be optional if you have required ones to the right.

// Do
Route::get('article/{id}/{slug?}', 'ArticleController@show');
...
function show($id, $slug = null) {}

// Don't
Route::get('article/{slug?}/{id}', 'ArticleController@show');
...
function show($slug = null, $id) {}

I do agree with comments above saying it might not be entirely logical to do so. You will need either slug or id to lookup your article in the database, but at the same time you'd hope only of them would suffice to find the exact same article.

If you really want to have an optional slug in order to make your URLs more "crawlable", SEO-firendly, memorable or what have you, here's a suggestion, building from the example above:

Route::get('article/{id}/{slug?}', array(
    'as'   => 'article.show',
    'uses' => 'ArticleController@show'
));

...

function show($id, $slug = null)
{

    $article = Article::find($id);

    if (!$slug) {
        return Redirect::route('article.show', array($id, $article->slug));
    }

    ...
}

I see no reason why anyone would try to access a slug-less URL, but that may be up to you and what you're trying to do with your app. This way at least you'd make the slug "optional", while making sure everyone ends up in the same spot with the full URL.

Upvotes: 3

Related Questions