我应该在Laravel中嵌套通往资源的路线吗?

时间:2018-11-18 07:18:59

标签: laravel laravel-5 routes laravel-routing

这可能有点主观,但我认为必须存在最佳实践(甚至在Laravel应用程序方面甚至是好的设计)。谷歌搜索导致很多事情与该问题的实际观点无关。


说我正在构建一个具有团队的Web应用程序,该团队可能包含项目,可能包含文档。

我应该设计路径,使文档位于其所属项目的路径之内,然后位于其所属团队的路径之内,还是将其保留在顶层?

据我所知,该频谱的两端值得讨论(其他选项只是中间的灰色):

嵌套

  

例如,可以在以下位置找到Doc C:/ teams / team-a / projects / project-b / documents / doc-c

这很容易做到,在路由文件中,我可以使用route groups帮助保持结构整洁。我认为这对用户来说更合乎逻辑,并且也许更方便(他们可以自己制定URL!)。我担心的是我正在向每个页面请求中导入复杂性:

  • 检查路由是否完整(即doc-c确实属于project-b),并且
  • 用户有权通过路由一直访问每个嵌套资产。

我应该在每个控制器方法的开头,对每个路由参数都对每个资源进行门/策略检查吗?否则,可以在哪里抽象呢?

关于路由完整性,我从未见过为此进行测试的示例-那么这不是常见的方法吗?如果我们不验证路线的完整性,那么页面可能会通过修改路线来显示混合信息(例如,/ teams / team-a / projects / project-Z / documents / doc-c将在文档上显示有关项目Z的信息-c的页面)。

无嵌套

  

例如,可在以下位置找到Doc C:/ documents / doc-c

在此示例中,每个资产都有其自己的基本路线,更像是我猜想的API。

不需要完整性检查,并且控制器将预先确定显示的其他资产以生成视图。

但是这个UX是否足够好?我见过的大多数网站都不这样做。

5 个答案:

答案 0 :(得分:3)

这是一个有趣的问题-正如您提到的那样,这可能有点主观,但值得讨论。

您触摸了几点,所以我将尝试分别解决。

嵌套与不嵌套

我认为要清除的第一件事是浏览器路由与API路由。如果您是在应用内部或外部提供API,则出于以下几个原因,我会避免使用嵌套路由:

  • 资源/ id格式非常标准,可以表达API的
  • 这使记录文档变得更加容易
  • 这使消费者应用更轻松地动态构造API请求

但是,您的问题似乎确实集中在浏览器路由上。在我看来,浏览器的路线可以而且应该是任何看起来不错的东西-网址(尤其是最近这些网址)都可以视为用户界面的一部分。例如,您可能会从“设置”页面转到设置(我希望看到/settings),如果我要进入“通知设置”部分,我希望看到/settings/notifications

这些路由起作用并与UX配合使用-它们几乎是面包屑,应该看起来像这样。

因此,我绝对会嵌套浏览器路由,而绝对不会嵌套API。

路由完整性

我认为您的问题的真正核心在于路线的完整性。我认为无论您是否选择嵌套,都需要假设某人正在篡改网址来检查权限-就像您认为用户已篡改表单输入一样。

基本上,您的路线(是否嵌套)都将作为输入,您需要进行验证。路由级中间件是一种方法,但是通常太通用而无法解决任何复杂的问题,因此您可能会发现使用控制器中间件(https://laravel.com/docs/5.7/controllers#controller-middleware)可以更轻松地解决它。

所以您可以执行以下操作:

public function __construct()
{
    $this->middleware('auth');

    $this->middleware('canViewProject')->only('show');

    $this->middleware('canEditProject')->except('store');
}

无论您使用Gates,Policy还是仅使用老式的中间件,都可能取决于项目的复杂性-但以上内容适用,无论如何-将url作为输入并相应地进行验证

答案 1 :(得分:0)

这一直是开发人员之间的讨论,即使Laravel的创建者也有这种说法,那么什么是最佳实践?

最近我看过泰勒·奥特威尔(Taylor Otwell)的一条推文,说他已经弃用了 Laravel文档中的嵌套路线部分,因为他不喜欢它,而当您打开Laracasts时,您会看到Jeffrey正在实现/series/php-testing/episodes/hello-world之类的概念。

正如我所说的那样,这是一个安静的论点,当涉及到这样的选择时,我总是做对我来说感觉很好的事情。因此,如果我是您,我既不会嵌套teams也不会嵌套projects,但也许我会嵌套projects/documents,所以我不会总是嵌套。

答案 2 :(得分:0)

这可能与原始问题有些偏离,但我认为Adam Wathan的Laracon US 2017演讲可能是此讨论的有用资源。 (https://www.youtube.com/watch?v=MF0jFKvS4SI

我对开发相对较新,因此在github上探索了很多代码库。我总是很难理解嵌套路线。因此,作为最佳实践,我宁愿不嵌套也不愿嵌套。

保持Adam所说的“按设计进行粗略处理”,imo是您要实现的一件事,就是简化了路由名称。如果我要在小组中工作,那是我更喜欢的一种模式。

但是,在提到您问题的倒数第二段时,我很难理解为什么不需要完整性检查。

答案 3 :(得分:0)

去年我一直在研究和完善它,最近偶然发现了一种优雅的解决方案。嵌套可以很好地完成,我坚持使用资源控制器和嵌套路由资源的点语法。

为了强制进行路线验证,我使用了类似以下内容的东西。有一个很好的答案here,它建议显式绑定有问题的模型。

所以

Route::resource('posts.comments', 'CommentsController');

您将使用

Route::bind('comment', function ($comment, $route) {
    return Comment::where('post_id', $route->parameter('post'))->findOrFail($comment);
});

这将自动在任何地方工作。如果需要,您可以测试要找到的上游参数,并且仅在这种情况下执行测试(例如,为仅指定注释的路线提供服务)。

答案 4 :(得分:-1)

我认为您应该利用角色概念,路由分组,中间件概念来构建此应用

对于与角色相关的事情,请检查https://github.com/spatie/laravel-permission,这是一个很好的软件包

例如:

Route::group(['middleware' => ['role:super-admin']], function () {
    //
});

使用上述程序包,您几乎可以扮演任何角色,权限相关的事情。

承担项目经理,开发人员等角色。

根据角色对路由进行分组,并根据需要分配适当的中间件。

对于网址:/ teams / team-a / projects / project-b / documents / doc-c

检查已通过身份验证的用户是否在团队a和项目b中起作用(您可以根据需要在中间件,控制器或自定义服务提供程序中进行检查)。

也只需检查https://laravelvoyager.com/

谢谢