Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

jeremyhart's avatar

Dynamic Router for database driven website

Hello,

I am building a website for which the pages are all dynamic, the layout is the same, but with different content blocks. I am wanting to make it SEO friendly where each page url consists of any number of categories and then a page name. i.e. home.com/cat1/sub-ca2/sub-cat3/page-name.

The router has to get the slugs from the url and return a view with the appropriate product data to populate that view.

I have search in internet in vain to try to find instruction on how to make the router for this. Can anybody shed some light on how this can be achieved?

Thanks heaps in advance and thanks to the awesome Laravel crew, Laravel is the best!

0 likes
10 replies
Paschal's avatar

Well, you have to be really really creative with your programming to get this to work as is... VERY VERY CREATIVE. The biggest challenge will be in the controller.

Now here comes the problem. The /cat1/sub-ca2/sub-cat3/ part, will it always be like this? Will every route have a cat1, sub-cat2, sub-cat3?

If YES then it's pretty easy.

First thing is to understand routing, optional route parameters etc.

I'll do this.

Routes.php

Route::get('/{category}/{sub-cat2}/{sub-cat3}/{page}', 'RouteController@index');

RouteController.php

function index($category, $subCat2, $subCat3, $page){
    
    $productsData = collect(); //You'll do your logic here with the categories to get the products data.

    //Make sure to sanitize the $page variable since it is gotten as input from the client. SECURITY CONCERNS

    return view($page)->with($productsData);
}

If NO, you will need extra programming magic. You'll also need to explain more & better what you want to achieve to see if I can be of help.

jeremyhart's avatar

Hello Paschal,

Thanks for trying to help, just to be clear, there could be any number of sub categories so it could be site.com/page or site.com/cat/page or site.com/cat/cat//cat/cat/page etc

Thanks for you help, it is much appreciated

sagar.jagtap's avatar

Hello jeremyhart,

can you try below code.

Route::get('test/{para?}', function ($para = null) { $arr = explode('/', $para); dd($arr); })->where('para', '(.*)');

you got all parameter in array .

Paschal's avatar

@jeremyhart That will be a challenge but it's solvable... Peep @sagar.jagtap response, you might have to explode parameters and get them as array then do your magic.

I can't really say if it's efficient but it might solve the problem.

1 like
Monaam's avatar

Hello ! From a first glance, you're problem is more a regex problem, and it's solvable. First you need to declare two route patterns, a categories slug and a product slug to use in our route like so '{categories_slug}/{product_slug}'.

  1. Product slug: it's just a regular slug pattern [a-z0-9-]+, that accepts all letters and characters and has to be at least one character long.
  2. Categories slug: it's a bit tricky this one LOL ! First of all we know that it's a group of slugs separated by slash, so my first thought was ([a-z0-9-]+\/)+ The problem is, while i was getting all the categories, i get the END SLASH with the pattern, and we don't want that, so i've put an optional '?' at the end of the slash and decided to force laravel routing to require a slash between the categories and the product (you'll see that in a moment). The second problem was the grouping, I was getting the last category as a first group, and that plays with laravel's understanding so we need to make sure the regex won't return the last item, we call that "Non-capturing group", so at the end it was ?:[a-z0-9-]+\/?)+. Now let's declare our patterns and route
Route::pattern('categories_slug', '(?:[a-z0-9-]+\/?)+');
Route::pattern('product_slug', '[a-z0-9-]+');
Route::get('{categories_slug}/{product_slug}', 'ProductController@show');

To note that we always need to parse the categories, by that i mean explode the whole string by the slash

class ProductController {
    ...
    public function show($categories_slug, $product_slug){
        $categories = explode('/', $categories_slug);
        ...
    }
    ...
}

Now it's up to you if you want to use a middleware to handle that, or just use the __construct() method, or even leave it in the controllers parameters

Hope i explained it well (I didn't try it tho, so if anything is wrong just ping me)

jeremyhart's avatar

Thanks for the help guys, much appreciated, i think sagar.jagtap will work the best for me.

Just one more thing, how do you return the assets in the public folder if I'm catching all the routes into this function?

jeremyhart's avatar

Well, you know how if you have image.jpg in your public directory then you can access it at site.com/image.jpg

sagar.jagtap's avatar

asset() is helper function of laravel you need to pass path inside of that function. Ex . public->images->demo.jpg

$path = asset('images/demo.jpg');

Please or to participate in this conversation.