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中实现了路由组和路由模型绑定的最佳实践?
谢谢!
答案 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中它还允许'-'