agb
agb

Reputation: 122

Laravel Route Model Binding: Check if a route parameter exists in model

I have this route:

Route::get('{country}/{federalstate?}/{city?}', ['as' => 'regions.show', 'uses' => 'RegionsController@show']);

Next I have a model Country with a few countries in it.

I want this route only to take effect, when given {country} exists in the model Country. I want to do this, because don't wan to use a prefix for that route.

The ugly way would be a regular expression. Ugly, because I would have to update it every time I add a new country to the model.

So what's the best way to accomplish what I want to do?

Maybe this could help -> https://laravel.com/docs/5.4/routing#route-model-binding - but I am a beginner, and I can't get it to work.

edit:

this might work:

Route::get('{country?}/{federalstate?}/{city?}', ['as' => 'regions.show', 'uses' => 'RegionsController@show'])->where([
    'country' => 'germany|usa|canada'
]);

But, as I said, I would have to change the Regex every time I add a new country to the database.

Upvotes: 2

Views: 3797

Answers (3)

krufkojat
krufkojat

Reputation: 11

In my opinion, you could pass Country to your controller as model. If there is no such model in your DB, Laravel will produce 404 error.

Upvotes: 0

agb
agb

Reputation: 122

Here's my solution for now:

in AppServiceProvider in the boot() method:

$available_countries = Country::select('slug')->get();

$available_countries = $available_countries->toArray();

$tmp = array();

foreach ($available_countries as $country)
{
    $tmp[] = $country['slug'];
}

Config::set('app.available_countries', $tmp);

and in my routes file:

Route::get('{country?}/{federalstate?}/{city?}', ['as' => 'regions', 'uses' => 'RegionsController@index'])->where([
    'country' => implode('|', config('app.available_countries'))
]);

Upvotes: 1

jackel414
jackel414

Reputation: 1686

As you suggested, Route-Model binding may be your best bet. You can see from the docs that if the model you've bound to your route does not exist, the route will return a 404.

Just be aware that the default functionality in Route-Model binding expects an ID from the URL. If you want to override that, you can do the following:

/**
 * Get the route key for the model.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'name';
}

Upvotes: 0

Related Questions