prigal
prigal

Reputation: 83

Laravel routes confusion with slugs

How can I handle 2 similar urls in my routes.php in Laravel Framework ?

Eg :

Code :

#Categories Pages
Route::get('{catSlug}', array('uses' => 'CategoriesController@show'));

#Product Page
Route::get('{productSlug}', array('uses' => 'ProductController@show'));

If i browse to mysite/shoes show method in CategoriesController is fired, but if I browse to mysite/adidas-model-1 it's not show method of ProductController but the one of CategoriesController which is fired.

Is there a nice way to achieve this in routes.php file ? Or do I route all to CategoriesController@show and if object is not found fire the show method of ProductController ?

Thanks.

Upvotes: 1

Views: 2685

Answers (3)

Xavi Martínez
Xavi Martínez

Reputation: 2161

Try to make it like this, this is how I use it.

Route::get('{slug}', function($slug) {

 // IF IS CATEGORY...
    if($category = Category::where('slug', '=', $slug)->first()):
      return View::make('category')
        ->with('category', $category);
 // IF IS PRODUCT ...
    elseif($product = Product::where('slug', '=', $slug)->first()):
      return View::make('product')
        ->with('product', $product);
 // NOTHING? THEN ERROR
    else:
      App::abort(404);
    endif;
});

Upvotes: 0

prigal
prigal

Reputation: 83

Thanks for your answers.

I really need to be free of what I choose for my slugs. So i found an other solution.

# Objects (cats or products)
Route::get('{slug}', array('uses' => 'BaseController@route'));

and in my BaseController file :

public function route($slug)
{
    // Category ?
    if($categories = Categories::where('slug', '=', $slug)->first()){  
        return View::make('site/categories/swho', compact('categories'));
    // Product ?
    }elseif($products = Products::where('slug', '=', $slug)->first()){
        return View::make('site/products/show', compact('products'));
    }
}

I first test for a Category object (I have less categories than products) and if not found I test for a product.

Upvotes: 1

Kryten
Kryten

Reputation: 15750

In the two routes you've shown, the router has no way of knowing when you're entering a catSlug and when you're entering a productSlug - they're both strings and there's no code there to distinguish them.

You can correct this by adding a where clause:

Route::get('{catSlug}', array('uses' => 'CategoriesController@show'))
    ->where('catSlug', '[A-Za-z]+');

Route::get('{productSlug}', array('uses' => 'ProductController@show'))
    ->where('productSlug', '[-A-Za-z0-9]+');

In the regular expressions above, I've assumed that categories are strings of upper and lower case letters only - no numbers, no spaces, no punctuation - and products include hyphens and numbers.

I should also add that the order of these declarations will be important. The product route also matches the category route, so the category route should be declared first, so it has a chance to fire. Otherwise, everything looks like a product.

Upvotes: 2

Related Questions