laravel - 雄辩的急切加载关系
问题描述
StackOverflow的各位好人,祝大家有个美好的一天(˘⌣˘)♡(˘⌣˘)
我是 Laravel 的新手,目前正在学习雄辩的关系(hasMany)
很抱歉这篇文章太长无法阅读,但我想澄清我在遇到问题之前所做的每一步,如果我的英语不好也很抱歉(⁄ ⁄•⁄ω⁄•⁄ ⁄)
所以我们开始
在我的用户模型中
public function posts() {
// A user can have many posts
return $this->hasMany('App\Post');
}
在我的 Post 模型中
public function owner()
{
// A post belongs to a user
return $this->belongsTo('App\User', 'user_id');
}
在我的帖子表中,我有 3 条简单的记录
|----------------------------------------------------------|
| id | user_id | body | ... | ... |
| 1 | 1 | My first post | ... | ... |
| 2 | 1 | Second post | ... | ... |
| 3 | 1 | Another post | ... | ... |
然后假设,我们想查看 id = 1 的用户以及他们创建的所有帖子,所以我使用下面的代码:
// AccountController
public function profile($id)
{
$user = App\User::with('posts')->findOrFail($id);
return $user;
}
// Will return data:
{
"id": 1,
"name": "Prof. Angela Runte Jr.",
"email": "mborer@example.org",
...
"posts": [
{
"id": 1,
"user_id": 1,
"body": "My first post",
...
},
{
"id": 1,
"user_id": 1,
"body": "Second post",
...
},
{
"id": 1,
"user_id": 1,
"body": "Another post",
...
}
}
在 Blade 视图中,我可以简单地获取如下数据:
// in profile.blade.php
$user->name
$user->...
@foreach($user->posts as $post)
// Show each post data
@endforeach
它以我想要的方式完美运行,感谢 Taylor Otwell 创建了一个惊人的框架 (´• ω •`) ♡</p>
然后我脑子里有了一个想法,让我们做一个用户可以向其他用户发帖的功能,为什么不呢?我们开始做吧!(✧ω✧)
因此,在我的 Post 迁移中,我更改了表架构:
从:
// Before
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignBigInteger('user_id');
$table->text('body');
$table->timestamps();
至:
// After
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('user_id');
// New column: nullable()
$table->foreign('for_id')->references('id')->on('users')->onDelete('cascade');
$table->unsignedBigInteger('for_id')->nullable();
$table->text('body');
$table->timestamps();
如您所见,我将 nullable() 放在“for_id”列中
换句话说,如果 for_id 为空,则该帖子仅属于发布该帖子的用户
否则,帖子属于发布帖子的用户以及预期用户 (for_id)。
然后在那之后,我跑
// I only use UserSeeder (wanna keep it simple tho)
php artisan migrate:fresh --seed
现在我们有 2 个 id = 1 和 2 的用户(耶!)
|----------------------------------------------------------------------------------------|
| id | name | email | ... | ... |
| 1 | Camden Kulas | lemke.fabian@example.net | ... | ... |
| 2 | Mrs. Roberta Stroman | ybartoletti@example.com | ... | ... |
让我们使用 tinker 创建虚拟数据
php artisan tinker
>> $user = App\User::first();
=> App\User {#3910
id: 1,
name: "Camden Kulas",
email: "lemke.fabian@example.net",
...
}
>> $user->posts()->create(['body' => 'New first post']);
=> App\Post {#4120
body: "New first post",
user_id: 1,
updated_at: "2020-08-30 03:42:43",
created_at: "2020-08-30 03:42:43",
id: 1,
}
// we create one for Mrs. Roberta Stroman (user with id #2)
>> $user->posts()->create(['for_id' => 2, 'body' => 'Hello there']);
=> App\Post {#3912
for_id: 2,
body: "Hello there",
user_id: 1,
updated_at: "2020-08-30 03:44:18",
created_at: "2020-08-30 03:44:18",
id: 2,
}
所以现在我们的帖子表中有 2 条记录
|--------------------------------------------------------------------|
| id | user_id | for_id | body | ... |
| 1 | 1 | NULL | New first post | ... |
| 2 | 1 | 2 | Hello there | ... |
我们仍然在用户 ID #1
>> $user->posts
=> Illuminate\Database\Eloquent\Collection {#4120
all: [
App\Post {#4125
id: 1,
user_id: 1,
for_id: null,
body: "New first post",
...
},
App\Post {#4128
id: 2,
user_id: 1,
for_id: 2,
body: "Hello there",
...
},
],
}
( ̄ω ̄) 好的,到这里为止,一切正常,让我们尝试使用用户 ID #2
在我看来,我想获取用户 id #2,以及所有由 id #2发布的帖子,以及其他人为 id #2 发布的所有帖子
>> $user = App\User::find(2);
=> App\User {#4121
id: 2
name: "Mrs. Roberta Stroman",
email: "ybartoletti@example.com",
...
}
>> $user->posts
=> Illuminate\Database\Eloquent\Collection {#4067
all: [],
}
Σ(°ロ°) 帖子是空的,为什么它是空的?
ఠ ͟ಠ 然后我尝试使用 with()
>> $user = App\User::with('posts')->find(2);
=> App\User {#4120
id: 2,
name: "Mrs. Roberta Stroman",
email: "ybartoletti@example.com",
...
posts: Illuminate\Database\Eloquent\Collection {#4123
all: [],
},
}
(ꐦ°᷄д°᷅) 什么??为什么帖子还是空的?щ(ºДºщ)
所以,找了好几天,还是不知道怎么解决(。╯︵╰。)
然后我试图改变我的用户模型:posts() 函数
从:
public function posts()
{
// A post belongs to a user
return $this->hasMany('App\Post');
}
至:
public function posts()
{
// In my logic like:
// Hey I want to fetch all posts that made by this user, **or where all posts that created by others for this user**
// Make sense in human language right?
return $this->hasMany('App\Post', 'user_id')->orWhere('posts.for_id', $this->id);
}
我退出了修补程序,然后再次重新进入修补程序
>> $user = App\User::first();
// return user id #1
>> $user->posts
// works fine, return all posts
(ಠ益ಠ) 现在我面临其他问题
>> $user = App\User::with('posts')->first(); // notice that I'm using with()
// tinker return the desired user, and also return ONLY one post
>> App\User {#4123
id: 1,
name: "Camden Kulas",
email: "lemke.fabian@example.net",
....
posts: Illuminate\Database\Eloquent\Collection {#4130
all: [
App\Post {#4128
id: 1,
user_id: 1,
for_id: null,
body: "New first post",
created_at: "2020-08-30 03:42:43",
updated_at: "2020-08-30 03:42:43",
},
// where is the second post?
],
},
}
然后我尝试使用用户 ID #2 更改修补会话
>> $user = App\User::find(2);
// return user id #2
>> $user = App\User::with('posts')->find(2);
// return user id #2, but no post (only array all)
所以不用再写了,我想问的问题
[#1] 为什么用户 #1 只获取一个帖子,同时他创建了 2 个帖子?
一篇没有 for_id (NULL) 的帖子,第二篇有 for_id 的帖子
[#2] 如何让用户 id #2 获取他们所有的帖子,以及为他们创建的帖子?
因为用户模型中的恕我直言 posts() 函数,对我来说非常有意义,但它不起作用
如有解释不清楚,会及时编辑
提前致谢
更新
我发现我可以通过这种方式简单地获取用户 X 的所有帖子和用户 X 的所有帖子:
$user = App\User::find(X);
$posts = $user->posts()->orWhere('for_id', X)->get();
return [
'user' => $user,
'posts => $posts
];
所以现在我想到了这个问题:
如何将 with() 用于 $posts?
// Like this
$user = App\User::with('allposts')->find(X);
// Return user X and all posts made by X and posted to user X
// So I can simply get data in view like this:
@foreach ($user->allposts as $post)
// Loop all posts by user X and for user X
@endforeach
解决方案
推荐阅读
- database - 用于存储股市数据的快速数据库
- python-3.x - 如何在 FastAPI 中编写多响应 BaseModel?
- function - 在 MATLAB 中计算正域上的卷积积分
- flutter - 删除项目后如何更新我的 GridView
- chart.js - 在图表 js 3.3.2 中,垂直网格线没有占据画布的全部高度
- c# - 通过使用 C# Linq 对多列进行分组来转换层次结构中的数据表
- vulkan - 使用 Vulkan/GPU 转换图像格式?
- ms-access - 循环 DoCmd.SendObject
- mongodb - 具有精简和保存功能的大型猫鼬查询
- kotlin - Kotlin MotionLayout 未按预期扩展