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

AydenWH's avatar

Wildcard Route

Hello everyone,

I would like to know how to implement a wildcard route which able to handle a different level of URL path and display the correct information and views layout.

Example my path can be something like this,

/
/category
/category/product
/category/product/1
/cart
/checkout/address
/checkout/payment
/about-us
...

Web.php

Route::get('/', 'Frontend\HomeController@index');
Route::get('/{path}', 'Frontend\HomeController@handler')->where(['path' => '.*']);

RouteController

// Explode the path into an array
$path = explode('/', $path);

// Calculate the level of the path
switch (count($path)) {
    case 1:
        if (
            $path[0] == "cart"
        ) {
            return view('frontend.' . $path[0]);
        }
        break;
    case 2:
        return view('frontend.' . $path[0] . '.' . $path[1]);
        break;
    case 3:
        return view('frontend.' . $path[0] . '.' . $path[1] . '.' . $path[1]);
        break;
    default:
        return view('frontend.home', ['universes' => $this->universes]);
        break;
}

Am I doing this correct? Is there any tutorial I can learn how to create a proper wildcard route?

0 likes
11 replies
Snapey's avatar

why when the router will do this for you? Sorry, this has to be asked

AydenWH's avatar

@Snapey

The reason why I using this method to know which views layout to display based on the URL path.

Whenever I created some new categories, it would fetch the correct layout and display the information of the page.

So, I don't need to create new route again and again whenever I created a new category.

But I am unsure whether it is a correct step or not.

JanakaDombawela's avatar

@WeeHong I think not.

So, I don't need to create new route again and again whenever I created a new category.

Then you have to create new case again and again whenever you create a new category. I think your approach is difficult. Try to parametrize a layout with the values from urls rather than create a layout for each url.

mushood's avatar
mushood
Best Answer
Level 41

Hello Weehong

Try this in your web.php

Route::get('/test/{wildcard}', function(){
  return "First";
});

Route::get('/test/second', function(){
  return "Second";
});

Now if you go to http://127.0.0.1:8000/test/second, You will see that it returns "First"

Which means that when you have a url, laravel will look into your web.php and match the FIRST correct pattern and ignore following

If you want to go ahead with your wildcard route, be sure to put it AT THE BOTTOM of your web.php file

Example:

/
/cart
/checkout/address
/checkout/payment
/about-us

/* AT THE BOTTOM */

/{category}/product/1
/{category}/product
/{category}

In this way, when you have /cart or /about-us, you can use normal routing. I assume you know how to do this part.

But for wildcard, you can handle just like in your code example. But now you only need to handle your special cases. I'm assuming you are using a database or similar to make it dynamic.

However, I would still express concern like others showed above. This is not really a recommended way.

Whether you store it in database or web.php, you still have to write it down somewhere. However, if it fits YOUR need , i hope this helps :)

2 likes
AydenWH's avatar

@mushood

Your explanation will definitely help me out.

My only concern is, if i hardcode all the URL.

End up the web.php will have a long list.

mushood's avatar

Another helpful tip would be to create separate files and then include them in web.php

Example

  1. userroutes.php
  2. adminroutes.php

Then in my web.php file

/*other routes */

include('userroutes.php');
include('adminroutes.php');
RonBPalmer's avatar

I have something similar. I am building a CMS for a large blog site. Everything that will resolve to a URL is derived from a base document and will have a unique slug. This is replacing a 15 year legacy system with many changed urls that need to be legitimate. Currently, I have a 404 processor that checks the list for any route that doesn't resolve and I track URLs that I miss and add them to the list.

I want to resolve the unique slug in the new system regardless of what path may come before it. There are reasons why there might be different ways into the same page. Essentially, unique slugs resolve to a canonical URL. I have over 500 active pages / posts / definitions / courses / lessons / etc. Writing a route command for each of these seems unnecessary.

The slug itself often changes. My wife entered small paragraphs as titles in WordPress over the years that resolved to massive slugs. I am greatly simplifying these going forward but need all existing backlinks to remain valid.

If I can extract the slug and ignore everything that comes before the slug, I can use a single route command to resolve to my DocumentController that will return the correct document reflecting the canonical link. The slugs are already in the DB, created when the document is created. This behavior is similar to WordPress where you can enter a slug and resolve to the proper page or post regardless of where in the hierarchy it may be.

If I'm reading this correctly, I should be able to have a route that resolves /{wildcard}/slug. Perhaps I need a wildcard for each level of the path i.e. "/{wildcard}/{wildcard}/slug." That's easy enough to test but if there is something better....

One thing I haven't found yet is how to return a document with the canonical URL rather than whatever they entered in the browser. I assume its something in the header like returning 200 but I haven't found it yet. Can you direct me to that?

Thanks.

RonBPalmer's avatar

I just solved this issue for all routes except "/" which is named 'home'. This one displays the originally entered route in the browser.

The first route below is the one that accesses the Controller to return my canonical page. The second route calls the first one by name and returns the canonical page with the proper canonical URL displaying in the browser. I still have to play with the return codes but this is the basic solution, I think.

 Route::get('/divorce-child-custody-glossary/glossary', [ResourceController::class, 'glossary'])->name('glossary');

 Route::get('/glossary', function () {return redirect()->route('glossary');});

I think this will work just fine for my needs.

Please or to participate in this conversation.