Laravel 渴望加载数据透视表关系
Posted
技术标签:
【中文标题】Laravel 渴望加载数据透视表关系【英文标题】:Laravel Eager Loading Pivot Table Relations 【发布时间】:2019-12-21 03:11:14 【问题描述】:在开发我的聊天应用程序时,我已经看了很多帖子很长一段时间了,但我似乎无法掌握如何实现以下目标:
我有什么: 3 表:
客户
频道
channel_client(数据透视表)
2 个型号:
应用\客户端
class Client extends Model
protected $table = "clients";
public function channels()
return $this->belongsToMany(Channel::class);
...
应用\频道
class Channel extends Model
public function clients()
return $this->belongsToMany(Client::class);
...
我想要实现的目标: 获取频道,其中包含客户端 X 和客户端 Y,仅此而已。 (我事先可以通过客户端模型访问客户端 ID)
我尝试修改了一下,结果如下:
>>> $client = App\Client::with('channels')->whereIn('id',[1,2])->get()
=> Illuminate\Database\Eloquent\Collection #3303
all: [
App\Client #3243
id: 1,
name: "John",
user_id: 1,
created_at: "2019-08-14 12:55:19",
updated_at: "2019-08-14 12:55:19",
channels: Illuminate\Database\Eloquent\Collection #3354
all: [
App\Channel #3249
id: 1,
name: "Web Development",
type: null,
created_at: "2019-08-14 12:52:32",
updated_at: "2019-08-14 12:52:32",
pivot: Illuminate\Database\Eloquent\Relations\Pivot #3362
client_id: 1,
channel_id: 1,
,
,
App\Channel #3360
id: 3,
name: "ios Development",
type: null,
created_at: "2019-08-14 12:52:32",
updated_at: "2019-08-14 12:52:32",
pivot: Illuminate\Database\Eloquent\Relations\Pivot #3321
client_id: 1,
channel_id: 3,
,
,
App\Channel #3363
id: 5,
name: "android Development",
type: null,
created_at: "2019-08-14 12:52:32",
updated_at: "2019-08-14 12:52:32",
pivot: Illuminate\Database\Eloquent\Relations\Pivot #3329
client_id: 1,
channel_id: 5,
,
,
],
,
,
App\Client #3283
id: 2,
name: "Lucy",
user_id: 2,
created_at: null,
updated_at: null,
channels: Illuminate\Database\Eloquent\Collection #3286
all: [
App\Channel #3364
id: 1,
name: "Web Development",
type: null,
created_at: "2019-08-14 12:52:32",
updated_at: "2019-08-14 12:52:32",
pivot: Illuminate\Database\Eloquent\Relations\Pivot #3248
client_id: 2,
channel_id: 1,
,
,
],
,
,
],
>>>
正如您在此处看到的,ID 为 1 的频道是用户的相互频道,因为用户 1 和用户 2 都订阅了频道 1。
我知道我的查询返回用户 ID 为 1 或 2 的所有用户及其频道,但如果我转而查询 App\Channel::with('users')... 我无法指定位置子句,因为我不知道它是什么频道 ID 是相互的。这就是我试图通过查询找出的。 所以这里是总结: 我想要一个 Eagerloading Query(否则我会使用 whereHas),它返回我指定的客户的相互通道。 非常感谢您的阅读。 我希望你能帮助我理解这一点。 问候!
编辑:所以从This Laravel Documentation Part 来看,它应该按照@Mohamed Ahmed 的描述工作,但是当我尝试它时,我得到以下结果,它似乎已经加载了所有频道,但也只有我指定的客户端(但仍然查询所有频道,这不是我的真正目标)
>>> $cha = App\Channel::with(['clients' => function($q) $q->whereIn('id',[1,2]); ])->get();
=> Illuminate\Database\Eloquent\Collection #3359
all: [
App\Channel #3365
id: 1,
name: "Web Development",
type: null,
created_at: "2019-08-14 12:52:32",
updated_at: "2019-08-14 12:52:32",
clients: Illuminate\Database\Eloquent\Collection #3403
all: [
App\Client #3398
id: 1,
name: "John Doe",
user_id: 1,
created_at: "2019-08-14 12:55:19",
updated_at: "2019-08-14 12:55:19",
pivot: Illuminate\Database\Eloquent\Relations\Pivot #3324
channel_id: 1,
client_id: 1,
,
,
App\Client #3240
id: 2,
name: "Lucy",
user_id: 2,
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot #3372
channel_id: 1,
client_id: 2,
,
,
],
,
,
App\Channel #3325
id: 2,
name: "Android Development",
type: null,
created_at: "2019-08-14 12:52:32",
updated_at: "2019-08-14 12:52:32",
clients: Illuminate\Database\Eloquent\Collection #3268
all: [],
,
,
... all the remaining channels here (too much code)
所以它是部分正确的。有什么想法吗?
【问题讨论】:
【参考方案1】:你绝对可以扭转它。但这意味着需要修补(明白双关语吗?)。
您想要做的是,访问 Channel 模型并执行 whereHas('users')
。魔法发生在这里:
$channel = App\Channel::whereHas('clients', function($q)
$q->whereIn('id', [1,2])->get();
)->get()
您可以在控制器中尝试此操作,或者将其作为返回值。
这基本上做的是,它调用clients
关系并在关系内运行条件。如果您的关系设置正确(与数据透视表设置正确的多对多关系),您应该没有进一步的问题。因此,现在上面的代码正在获取所有具有 id 1 和 2 的客户端的通道。
希望这会有所帮助。
快乐编码:)
【讨论】:
首先,感谢您的评论。 Tinkering 的意思是“php artisan tinker”并在其中编写一些代码,我发布的 sn-p 来自 tinker,因此我不必创建所有内容,只需一时兴起尝试一下。我会尽快试试这个。 是的,我知道修补匠是什么。我想开个玩笑。不过没关系 哦,我很抱歉:D 这是漫长的一天,我有点读过“明白双关语了吗?”呵呵,我已经更新了我的帖子,请你有空的时候看看它,仍然想继续帮助我。 等等,你的意思是所有剩余的频道都没有用户1和2吗? 没错。事情是这样的:只有频道 1 有用户 1 和 2,但是有多个频道,所以在返回的结果中显示频道 1 有用户 1 和 2,(参见 #3365)但频道 2 没有他们(客户端数组是空的)这是正确的。现在的问题是,为什么通道 2(以及所有其他空通道)会返回?以上是关于Laravel 渴望加载数据透视表关系的主要内容,如果未能解决你的问题,请参考以下文章