Sam Parmenter
Sam Parmenter

Reputation: 1841

Laravel Routes Issues when using wildcards

I have looked in quite a few places to no avail so I thought it was time to ask the experts.

I am playing about with laravel and I am having some issues with routing.

I have a cms of sorts and also a product catalogue, each of which uses no prefix to the pages.

A product might be 'example.com/my-product' and a page might be 'example.com/my-page'

In my routes I want to check if the url matches a page or a product or neither and then redirect to a specific controller/action depending on which it is.

currently I have

Route::any('/{slug}', function($slug) {
    $page = App\Models\Page::firstByAttributes(['slug' => $slug]);
    if($page) {
     // go to pagesController@find
    }
})->where('slug', '.*');

To differentiate between a page and a product is fine, I'll just pop an elseif after the if($page) for the product check but I am stumped as to how to get to the PagesController once I have determined that the url points to a page on the db.

Any help would be massively appreciated.

Edit:

My Pages Controller:

class PagesController extends BaseController {

    public function find()
    {
        echo 'asdaasda'; die;
    }
}

I can get this to work after a fashion but its not what I want. I need the url to remain as it was and the PagesController to handle the processing and rendering of the page. The only way I can get it to work is by adding a Route::controller('pages', 'PagesController') to the routes file then modifying the find function to getFind but that just ends up with a url that looks like example.com/pages/find/ rather than the original url that might have been something along the line of example.com/about-us.

Upvotes: 0

Views: 923

Answers (2)

Sam Parmenter
Sam Parmenter

Reputation: 1841

I have no idea if this is super bad practice but the only way I can see to get around this issue is to do the following in routes.php.

$url = \URL::current();
$url = explode('/', $url);
$end = end($url);

if($page = App\Models\Page::firstByAttributes(['slug' => $end])) {
    Route::get('/'.$end, 'PagesController@find');
} elseif($product = App\Models\Product::firstByAttributes(['slug' => $end])) {
    Route::get('/'.$end, 'ProductsController@find');
}

This basically gets the final part of the url and then checks if we have a page with that url and add the route for that specific page, if not, it checks if we have a product that fits the url and adds the route for that product.

If anyone has a cleaner solution I would love to know. I can't imagine that laravel doesn't have a way of creating routes based on database pages without having to either prefix them all with something like "pages/page-url".

Upvotes: 0

Glad To Help
Glad To Help

Reputation: 5387

Try this

Route::any('/{slug}', function($slug) {
    $page = App\Models\Page::firstByAttributes(['slug' => $slug]);
    if($page) {
      return Redirect::action('pagesController@find', array($page));
   }
})->where('slug', '.*');

You can also consider using route filters to achieve this in a slightly more readable way.

Upvotes: 2

Related Questions