Gravy
Gravy

Reputation: 12445

Laravel - using 'where' in routes.php to query a model

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

Answers (3)

Amir Bar
Amir Bar

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

Anam
Anam

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

ollieread
ollieread

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

Related Questions