2
votes

I have a categories table that looks like this:

-- id   -- parent_id             -- name
    1             0              electronics
    2             1              Televisions
    3             2             LCD TVs
    4             2             Plasma Tvs
    5             1              DVD Players
    6             1              Bluray Players
    7             0             Home Appliances
    8             7            Cookers
    9             7            Fridges & Freezers
    10            0            Fashion
    11            10            Mens Clothing
    12            11             Shirts
    13            10            Womens Clothing
    14            13            Skirts

and so on - the problem I have is some categories are only single and others can be 3 or 4 deep.

I have a list page that will paginate all items in a given category and will show the child categories of that category for further drilling down and so on until the last child is reached.

I have 2 problems 1 being how do I route this so it will match /products/{parent_category}/?if_exists_child_category/if_exists_child_child/if_exists_child_child_child

the next is on the home page I have featured products and need to link to the product page and include the full category path to it product/parent_cat/if_exists_sub_cat/if_exists_sub_sub_cat/if_exists_sub_sub_sub_cat/product_name * I have an idea how to do this one the routing issue is my main problem.

or even if I could just capture everything after prodocucts/ I could then explode it into an array and cycle through the categories and or find the product slug and display the correct view.

Thanks All in advance and Happy Almost Christmas :)

1
Are those URL segments id's or the name of the category (for SEO)?lukasgeiter
Yes they are for category names for SEO I can pull the product just by its slugAdrian Brown

1 Answers

3
votes

I propose you change your URLs so they have a part that will be used for routing and one that will be used for SEO purposes. Here's what I mean:

/products/view/{product_id}/{category_name}/{category_name}/{etc}/{product_name}
/products/category/{category_id}/{category_name}/{category_name}/{etc}

This has the advantage that you can ignore the fact that you won't always have the same numbers of categories. Your routing only depends on the first few segments of the URL.

Route::get('products/view/{id}/{seo-slug?}', array('as' => 'product', function($id, $seoSlug){
    $product = Product::find($id);
    // ...
}))->where('seo-slug', '.*');

Route::get('products/category/{id}/{seo-slug?}', array('as' => 'category', function($id, $seoSlug){
    $category = Category::find($id);
    // ...
}))->where('seo-slug', '.*');

Now when it comes to generating links you will have a hard time just using Laravels helper functions. Let's create our own. One way is to add a function to the Product and Category models. (You could also write a function that's independent of the models, the core functionality stays the same)

Product

public function getUrl(){
    $categoryNames = array('cat1', 'cat2', 'cat3'); // use/create a function on the category model that uses recursion to determine all the categories of the tree
    $seoSlug = implode('/', $categoryNames);
    // ... maybe add other stuff to $seoSlug
    return route('product', array($this->id, $seoSlug));
}

Category

public function getUrl(){
    $categoryNames = array('cat1', 'cat2', 'cat3'); // use the same function as above
    $seoSlug = implode('/', $categoryNames);
    // ... maybe add other stuff to $seoSlug
    return route('category', array($this->id, $seoSlug));
}

Redirect "wrong" URLs

If you want, you can now redirect URLs that have a wrong SEO slug. Meaning it would also be possible to just enter:

/products/view/183

This can also serve as some kind of URL shortening for sending links in emails etc.

To validate the URL and then redirect you can just compare the current URL with a "freshly" generated one. Like this:

Route::get('products/view/{id}/{seo-slug?}', array('as' => 'product', function($id, $seoSlug){
    $product = Product::find($id);
    $productUrl = $product->getUrl()
    if(Request::url() !== $productUrl){
        return Redirect::to($productUrl);
    }
    // ...
}))->where('seo-slug', '.*');

Oh and Merry late Christmas to you too!