简化的场景如下:
我的数据库中有几页(理想情况下不超过 10-20,但没有硬性限制)。它们都有一些内容和一个“slug”(有些slug包含正斜杠,如果这很重要的话)。我正在尝试将这些 slugs 的路由注册到显示给定页面内容的 PageController
。以下是我对该方法的想法:
- 注册一条“catch 'em all”路线(这应该是最后注册的路线)。这绝对是糟糕的。
- 从数据库中查询所有链接并注册指向它们的单独路由。这很简单,但我必须查询数据库(这可能不是最佳的)并注册数十条,可能是数百条路线。
- 我还尝试过:注册一个 HTTP 中间件,使用
$request->path()
获取查询参数,检查这是否是现有的 slug,如果是,则将其传递给页面 Controller
。我只需调用Route::get($request->path(), 'PageController@show')
即可实现此目的。
最后两种方法似乎都有效,但有一个问题:如何告诉 Controller 显示哪个页面?
或者有更好的方法吗?
提前致谢
编辑:我绝对不想使用“前缀”并将 slug 作为参数添加到其中。定义的 slug 应该是页面的确切 URL。
最佳答案
您列出的所有方法都可以是解决此问题的有效方法(即使是第一个方法,如果您在路线上附加 where
条件)。然而,在我看来,从性能角度来看,最好的方法将基于第二种解决方案,并且是在需要时生成路由并将其写入文件,然后缓存它们。所以我会这样做:
Warning: This approach only works if you don't have any Closure based routes
1. 创建一个单独的路由文件,用于存储页面路由,假设在 app/Http/Routes/page.php
中。您将在此处编写页面的路由定义。您还需要将其添加到 App\Providers\RouteServiceProvider
类的 map
方法中:
public function map(Router $router)
{
$router->group(['namespace' => $this->namespace], function ($router) {
require app_path('Http/routes.php');
require app_path('Http/Routes/page.php');
});
}
2. 然后您需要生成页面的路由定义并将其写入该文件。像这样的东西应该足够了:
$path = app_path('Http/Routes/page.php');
$definition = "Route::get('%s', 'PageController@show');\n";
// Remove the routes file so you can regenerate it
if (File::exists($path)) {
File::delete($path);
}
// Write the new routes to the file
foreach (App\Page::all() as $page) {
File::append(sprintf($definition, $page));
}
// Rebuild Laravel's route cache so it includes the changes
Artisan::call('route:cache');
上面的代码应该在特定的 events 上执行您可以附加到 Page
模型:created
、deleted
、updated
(但仅当 slug 被修改时)更新期间)。
3. 要访问 Controller 中的页面详细信息,您只需使用请求的路径
,因为那是您的 slug。所以这样做:
public function show(Request $request)
{
// You need to prepend the slash for the condition since
// the path() method returns the request path without one
$page = App\Page::where('slug', '/' . $request->path())->get();
// Do your stuff...
}
好了,现在您已经有了所有页面的路由定义。事实上,它们被缓存可以减轻当有大量路由时您可能会遇到的任何性能损失,并且您仅在更改这些路由时才接触数据库,而不是针对每个请求。
关于php - Laravel - 如何将参数传递给路由?有更好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35464689/