Laravel 8 - 友好 url 根据匹配(产品、类别、页面)调用多个控制器 - 如何设计?

Laravel 8 - friendly url that call multiple controllers depending on match (products, categories, pages) - How to design it?

我想建立一个路线,捕捉干净的 seo 友好 url 并调用正确的控制器来显示页面。示例:

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]

所以我有应用程序路线:

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

每个友好 url 都是唯一的 url(字符串),因此 pages/products/categories 之间没有重复。 urls 之间也没有模式 - 它们可以是 seo 中使用的任何字符串(仅文本加破折号/有时是参数)。

构建一个数据库 table 以确保所有 url 都在适当的位置并提供调用信息(url | controller_name | action_name) - 例如。

另一个问题是 - 如何根据使用的 url 调用不同的控制器? (对于上面的例子 -> RouteController catch friendly urls - 在 db table 中找到匹配项 -> 然后调用正确的控制器)

非常感谢您的帮助。 祝你有美好的一天

马克

如果你像这样为每种类型使用前缀会更好:

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]

然后为了实现这个,像这样创建三个路由

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

这些 URL 对 SEO 友好

您需要创建一个 table 调用 slug。 然后为每个页面、产品、类别创建一个唯一的 slug(可以自动生成或指定)。 slug 记录也有用于获取控制器和参数的列,例如:typeid

您可以采用两种方法。

主动:

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');
}

然后您可以通过例如

在适当的控制器中确定产品
$actualItem = Product::where('slug', request()->path())->first();

这种方法的缺点是所有路由都会在每个请求上注册,即使它们没有被使用,这意味着您在每个请求上访问数据库以填充它们。此外,使用此方法时无法缓存路由。

被动:

在这种方法中,您使用后备路线:

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);
});