Laravel路由:具有前缀和路由模型绑定的多路由组

时间:2020-09-18 05:02:35

标签: laravel laravel-routing

SO的好人!

我有一个关于Laravel Route的问题,我无法解决。

在User.php模型中,我使用getRouteKeyName()函数

public function getRouteKeyName()
{
    return 'user_name';
}

以及在Post.php模型中

public function getRouteKeyName()
{
    return 'uuid';
}

在用户表中,有1条记录

|----------------------------|
| id | ... | user_name | ... |
| 1  |-----|  @simple  |-----|

在帖子表中

|------------------------------------|
| id | ... | uuid              | ... |
| 1  |-----| abcd-123-efg-456  |-----|

在途中(web.php)

// for post (key: uuid)
Route::group(['prefix' => '{post}'], function () {
    Route::get('/', function (Post $post) {
        return $post;
    });
});

// for users (key: user_name)
Route::group(['prefix' => '{user}'], function () {
    Route::get('/', function (User $user) {
        return $user;
    });
});

然后说我们访问网址: www.example.test/@simple/

在调试栏中,我看到查询:

posts中选择*,其中uuid ='@simple'限制1

我尝试过的事情

[#1]我将where子句放在帖子和用户的路由组中

Route::group([
    'prefix' => '{post}',
    'where' => [
        'post' => '^[a-zA-Z0-9-]{36}$' // I'm not Regex professional
    ]
], function () {
    Route::get('/', function (Post $post) {
        return $post;
    });
});

Route::group([
    'prefix' => '{user}',
    'where' => [
        'user' => '^(@)[a-zA-Z0-9]$' // I'm not Regex professional
    ]
], function () {
    Route::get('/', function (User $user) {
        return $user;
    });
});

因此,让我们再次尝试访问以下网址: www.example.test/@simple

我得到了404

[#2]我同时删除了用户模型和帖子模型中的getRouteKeyname

重新访问网址: www.example.test/@simple ,仍然显示404

[#3]我尝试放置路由模型绑定列名称

Route::group([
    'prefix' => '{post:uuid}', // This is what I changed
], function () {
    Route::get('/', function (Post $post) {
        return $post;
    });
});

Route::group([
    'prefix' => '{user:user_name}', // This is what I changed
], function () {
    Route::get('/', function (User $user) {
        return $user;
    });
});

仍然,查询结果相同:> posts中选择*,其中uuid ='@simple'限制1

我要实现的目标

假设我们访问网址: www.example.test/@simple

获取user_name@simple的用户,或者如果该用户不存在,则返回404

对于帖子也是如此

我们访问网址: www.example.test/abcd-1234-efgh-5678

使用uuid获取帖子是abcd-1234-efgh-5678或404(如果不存在)

问题:

[#1]如何告诉Laravel Route:我有2个具有不同模型绑定的Route组?抱歉,这个问题有点令人困惑,因为我的英语不太好

[#2]我是否在Laravel中实现了路由组和路由模型绑定的最佳实践?

谢谢!

2 个答案:

答案 0 :(得分:0)

您打算获得什么结果? 如果您正在做我想做的事情(试图查看帖子中的内容),则需要返回类似$ post-> content的内容(用要获取的列替换内容),甚至可能要视图,使输出更好,并使用控制器进行更多处理。

对于路由模型绑定,您可以参考this,这两种方法都可以使用table:column和getRouteKeyName,但是,第一种方法不会更改默认列,如果使用{ {1}}用于另一条路由,它仍将使用ID列,但是,第二条更改默认值,如果您将{user}用于另一条路由,它将使用您指定的列。

此外,您应该使用{user}user/{user:user_name}之类的字词,而不是仅仅使用post/{post:uuid}{user:username}之类的字词,因为它不会知道您选择的路线重新使用。 uri必须不同。

按您放置的顺序评估路由,这意味着带有{post:uuid}的第二条路由将覆盖带有{post:uuid}的路由,因为它们具有相同的uri,也就是说,它们都包含1个通配符,仅此而已。要解决此问题,您只需通过添加静态部分来使它们的uri不同,例如,像下面的示例一样,在{user:username}之前添加post /和/或在{post:uuid}之前添加user /:

{user:user_name}

为清楚起见,您的2条路由具有相同的1个通配符的uri,没有别的,因此,与此uri一起出现的最后一个将覆盖具有相同uri的所有先前路由。意味着之前所有具有相同uri的先前路由都将被视为不存在,并且当您使用 / [在此处插入内容] 格式的uri进入路径时,它符合具有1个通配符的格式,并且只会转到您指定的最后一个通配符,即用于帖子的通配符。

由于用户的路线是在帖子的路线之前声明的,并且它们共享相同的uri,因此将仅使用帖子的路线。即使您试图查找用户,它仍然会使用发布路线,如果不存在带有与您提供的user_name相同的uuid的uuid的“发布”,即使确实存在具有该用户的用户,它仍然会返回错误用户名。

此外,如果只有1条路由,则不需要路由组,但是如果将来要向该组添加更多路由,则将更易于阅读和方便。

答案 1 :(得分:0)

据我所知,这是您需要进行的更改,并且可以生效, 路线/web.php

Route::group([
    'prefix' => 'post/{post:uuid}'
], function () {
    Route::get('/', function (Post $post) {
        return $post;
    });
});

Route::group([
    'prefix' => 'user/{user:user_name}'
], function () {
    Route::get('/', function (User $user) {
        return $user;
    });
});

您在上面使用的正则表达式只是过滤了{argument}并检查{argument}是否基本上是字母数字,在以上两种情况下,它的工作原理相同,只是在user_name中它还允许'-'