Reputation: 12445
I am looking to flatten my routes for an ecommerce store for SEO purposes.
I would like to create the following routes:
Route::get('/{country}', ['uses' => 'Store\ProductController@browseCountry']);
Route::get('/{category}, ['uses' => 'Store\ProductController@browseCategory']')
The country
and category
must be dynamic.
I would like to know if something like the following is possible? and the best way of achieving.
// Route 1
Route::get('/{country}', ['uses' => 'Store\ProductController@browseCountry'])
->where('country', ProductCountry::select('slug')->get());
// Route 2
Route::get('/{category}', ['uses' => 'Store\ProductController@browseCategory'])
->where('category', ProductCategory::select('slug')->get());
example routes:
/great-britain should be routed via Route 1
/china should be routed via Route 1
/widgets should fail route 1, but be routed via Route 2 because
widgets are not in the product_country table but are in
the product_category table
I know that I can hardcode my routes with possible countries:
Route::get('/{country}', ['uses' => 'Store\ProductController@browse'])
->where('country', 'great-britain|china|japan|south-africa');
However this is clumsy and tedius. I would like to get the list of countries from the database.
Upvotes: 2
Views: 3225
Reputation: 3105
i will do it this way i choose the country model because there are less models+ you need to cache that: change lists('name') to the country name column
Route::get('/{country}', ['uses' => 'Store\ProductController@browseCountry'])
->where('country', implode('|',ProductCountry::select('slug')->lists('name')));
what is does is select all countries name and return them as array like this
('usa','england','thailand')
and use implode with '|' as glue return this:
usa|england|thailand
so your final route is like this:
Route::get('/{country}', ['uses' => 'Store\ProductController@browseCountry'])
->where('country', 'usa|england|thailand');
Upvotes: 3
Reputation: 12169
You need route filters to achieve that.
place the following code to filters.php
or in the route.php
file
Route::filter('country', function()
{
$country = Country::where('slug', Route::input('country'))->first();
if( ! $country) {
dd("We do not support this country");
// Redirect::route('home');
}
});
and finally your route:
Route::get('country/{country}', array('before' => 'country', 'uses' => 'Store\ProductController@browseCountry'));
Upvotes: 0
Reputation: 6143
Okay, so after reviewing your updated question, you'll want to create a method within your respective models to concatenate all available slugs with the | character, so you'd call something like:
Route::get('/{country}', ['uses' => 'Store\ProductController@browseCountry'])
->where('country', ProductCountry::getSlugs());
This would pretty much return 'great-britain|china|japan|south-africa' like in your example, except you wouldn't have to write it.
I would however, strongly recommend, that you give the routes something a bit more, /country/{country} or /category/{category} otherwise it's confusing, and the URI structure is often this way so that users can accurately see where they are.
Upvotes: 0