laravel - Laravel 渴望加载与基于父级的条件的关系
问题描述
我有这个查询来列出所有用户及其对应关系。
用户有很多任务
每个任务有很多工作时间,这些工作时间可以有不同的用户
即,每个任务可以由不同的用户共享,因此他们对每个任务都有单独的工作时间。
我试过下面的代码
$users = User::select('users.id', 'users.first_name', 'users.last_name', 'users.contract_type')
->with([
'tasks' => function($query) use ($from, $to){
$query->whereBetween('date', [$from, $to])
->select('tasks.id', 'tasks.date');
},
'tasks.worktimes' => function($query) {
//$query->where('user_id', ?)
$query->withCount([
'tags as late_tag_count' => function ($subQuery) {
$subQuery->where('tags.id', 1);
},
'tags as early_tag_count' => function ($subQuery) {
$subQuery->where('tags.id', 2);
},
'tags as others_tag_count' => function ($subQuery) {
$subQuery->where('tags.id', 3);
}
]
);
}
])
->get();
这里的关系tasks.worktimes还获取其他用户的工作时间(这是预期的),但我想将其限制为仅获取父用户的工作时间。任何人请帮我弄清楚我应该使用什么其他条件来实现这一目标?
楷模
用户.php
public function tasks()
{
return $this->belongsToMany(Task::class, 'task_members')->withTimestamps();
}
任务.php
public function worktimes()
{
return $this->hasMany(Worktime::class, 'task_id');
}
工作时间.php
public function task()
{
return $this->belongsTo(Task::class);
}
public function users()
{
return $this->belongsToMany(User::class, 'task_members', 'task_id', 'user_id', 'task_id');
}
解决方案
闭包中的$query
QueryBuilder 仍然是一个实例,因此您也可以预先加载它
$users = User::select('users.id', 'users.first_name', 'users.last_name', 'users.contract_type')
->with([
'tasks' => function ($query) use ($from, $to) {
$query->with([
'worktimes' => function ($subQuery) {
$subQuery->withCount(
[
'tags as late_tag_count' => function ($subsubQuery) {
$subsubQuery->where('tags.id', 1);
},
'tags as early_tag_count' => function ($subsubQuery) {
$subsubQuery->where('tags.id', 2);
},
'tags as others_tag_count' => function ($subsubQuery) {
$subsubQuery->where('tags.id', 3);
}
]
);
}
])
->whereBetween('date', [$from, $to])
->select('tasks.id', 'tasks.date');
}
])
->get();
这样,工作时间和总计数按任务分组,任务按用户分组
编辑 1
在您必须先检索每个用户之后,您可以延迟加载每个用户的工作时间。然而,这不是很好,特别是如果有很多用户
$users = User::select('users.id', 'users.first_name', 'users.last_name', 'users.contract_type')
->with([
'tasks' => function ($query) use ($from, $to) {
$query->whereBetween('date', [$from, $to])->select('tasks.id', 'tasks.date');
}
])
->get();
foreach ($users as $user) {
$user->tasks->load([
'worktimes' => function ($query) use ($user) {
$query->where('user_id', $user->id)
->withCount([
'tags as late_tag_count' => function ($subQuery) {
$subQuery->where('tags.id', 1);
},
'tags as early_tag_count' => function ($subQuery) {
$subQuery->where('tags.id', 2);
},
'tags as others_tag_count' => function ($subQuery) {
$subQuery->where('tags.id', 3);
}
]);
}
]);
}
编辑 2
您已经belongsToMany
在 Worktime 模型上建立了用户 ( ) 关系。在这种情况下,在 User 模型上定义该关系的倒数将最有效。
//User.php
public function worktimes()
{
return $this->belongsToMany(Worktimes::class, 'task_members', 'user_id', 'task_id', 'user_id');
}
//YourController.php
$users = User::select('users.id', 'users.first_name', 'users.last_name', 'users.contract_type')
->with(
[
'tasks' => function ($query) use ($from, $to) {
$query->whereBetween('date', [$from, $to])->select('tasks.id', 'tasks.date');
},
'worktimes' => function ($query) {
$query->withCount([
'tags as late_tag_count' => function ($subsubQuery) {
$subsubQuery->where('tags.id', 1);
},
'tags as early_tag_count' => function ($subsubQuery) {
$subsubQuery->where('tags.id', 2);
},
'tags as others_tag_count' => function ($subsubQuery) {
$subsubQuery->where('tags.id', 3);
}
]);
}
]
)
->get();
希望这可以帮助。
推荐阅读
- file-upload - 如何在 Clojure 中预览文件上传的图像和文件名?
- ios - Swift - 使用 tableView.dequeueReusableCell 时数据未正确显示
- javascript - 需要了解表格结构才能抓取网页
- php - PHPMailer - php openssl 返回 IP 地址而不是主机名作为 CN?
- smalltalk - 可以创建一个独立的方法/函数(没有任何类)
- spring - 使用 Java 对象列表调用 Oracle 过程,作为 Spring Boot 的参数
- android - 具有网络约束的 WorkManager 未在 android 9 模拟器上运行
- jquery - 使用按钮单击删除 div 行
- react-native - undefined 不是对象(评估 '_expo.default.Constants')
- mysql - Docker MySQL 连接 DBeaver