Developer654079525's avatar

Dynamic routes

Should I / can I delegate the task of generating dynamic routes from the database to some code or should I simply list them in the web file? This messes things up for all the routes that follow:

Route::get('/{categoryslug}', [PagesController::class, 'category'])->where('categoryslug', '[A-Za-z0-9-_]+')->name('page.category');

My alternatives are to list all the top level routes by hand

Route::get('/something1', [PagesController::class, 'category'])->name('page.category');
Route::get('/something2', [PagesController::class, 'category'])->name('page.category');

Adding a name in between would solve my problems as:

Route::get('/categories/{categoryslug}', [PagesController::class, 'category'])->name('page.category');

But I would like to keep those roots as immediate levels. How to approach solving this? Is placing a dynamic code in the boot section an option?

0 likes
4 replies
Glukinho's avatar
Level 30

If you have Category model with slug column, then this route will catch them all (note a colon : in {category:slug}):

Route::get('/{category:slug}', [PagesController::class, 'category'])->name('page.category');

In PagesController you can have your category as a model ready for using:

// PagesController.php

public function category(Category $category)
{
	// do what you want with $category model
}

You shouldn't generate anything manually.

https://laravel.com/docs/12.x/routing#customizing-the-default-key-name

1 like
Glukinho's avatar

@Developer654079525 I don't really get your point, can you explain what you're trying to achieve?

In general, if you use {category} in your route and inject Category $category in your controller's constructor, then you have a category model in controller. If you want to bind another model, you should use it in route/constructor the same way, along with category.

For example:

Route::get('{category:slug}/{page}', ....

// Controller
public function category(Category $category, Page $page) 
{
    // You have $category model and $page model
    // ...
}

Then URL http://yourapp.com/my-category/123 will bring you to a controller with two models already instantiated and retrieved from database:

  • $category having slug = 'my-category'
  • $page having id = 123
1 like
martinbean's avatar

@developer654079525 If you have some sort of CMS where users can create pages with whatever slugs, then I’d use a fallback route for this in past.

You basically specify a controller that can be called when no other routes match, giving you a “last chance” to match the route before a 404 is returned:

Route::fallback(DynamicPageController::class);
class DynamicPageController extends Controller
{
    public function __invoke(Request $request)
    {
        $path = $request->path();

        $page = Page::query()->where('path', '=', $path)->firstOrFail();

        return view('page.show')->with(compact('page'));
    }
}

So this will either retrieve the page from the database with the path specified, or return a 404.

1 like

Please or to participate in this conversation.