skip to Main Content

i would like to build a route that catch clean seo friendly url and call correct controller to display page. Examples:

https://mypage.com/some-friendly-url-separated-with-dashes [PageController]
https://mypage.com/some-cool-eletronic-ipod [ProductController]
https://mypage.com/some-furniture-drawers [CategoryController]

So I have in app route:

Route::get('/{friendlyUrl}', 'RouteController@index');

Each friendly url is a unique url(string) so there is no duplicate between pages/products/categories. There is also no pattern between urls – they could be any string used in seo(only text plus dashes/ sometimes params).

Is it wise to build one db table that keeps all urls in on place with info what to call ( url | controller_name | action_name) – as an example.

Another question is – how to call different controllers depending on url used? (for above example -> RouteController catch friendly urls -finds match in db table -> then calls correct controller)

Many thanks for any help.
Have a nice day

Mark

3

Answers


  1. It’d be better if you just use a prefix for each type like this:

    https://mypage.com/pages/some-friendly-url-separated-with-dashes [PageController]
    https://mypage.com/products/some-cool-eletronic-ipod [ProductController]
    https://mypage.com/category/some-furniture-drawers [CategoryController]
    

    Then for achieving this, create three routes like this

    Route::get('pages/{friendlyUrl}', 'PageController@index');
    Route::get('products/{friendlyUrl}', 'ProductController@index');
    Route::get('category/{friendlyUrl}', 'CategoryController@index');
    

    These URLs would be SEO friendly

    Login or Signup to reply.
  2. You need create a table call slugs.
    Then create a unique slug (can be auto generated or specified) for each page, product, category.
    slug records also have columns to get Controller and params, ex: type and id

    Login or Signup to reply.
  3. There’s two approaches you can take to this.

    Proactive:

    In web.php

    $slugs = Product::pluck('slug');
    foreach ($slugs as $slug) {
        Route::get($slug, 'ProductController@index');
    }
    
    $slugs = Category::pluck('slug');
    foreach ($slugs as $slug) {
        Route::get($slug, 'CategoryController@index');
    }
    
    $slugs = Page::pluck('slug');
    foreach ($slugs as $slug) {
        Route::get($slug, 'PagesController@index');
    }
    

    Then you can determine the product in the appropriate controler via e.g.

    $actualItem = Product::where('slug', request()->path())->first();
    

    The downside to this approach is that all routes are registered on every request even if they are not used meaning you hit the database on every request to populate them. Also, routes can’t be cached when using this approach.

    Reactive:

    In this approach you use the fallback route:

    In web.php:

    Route::fallback(function (Request $request) {
       if (Page::where('slug', $request->path())->exists()) {
            return app()->call([ PageController::class, 'index' ]);
       }
       if (Category::where('slug', $request->path())->exists()) {
            return app()->call([ CategoryController::class, 'index' ]);
       }
       if (Product::where('slug', $request->path())->exists()) {
            return app()->call([ ProductController::class, 'index' ]);
       }
       abort(404);
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search