Laravel Eloquent 按关系对结果进行分组
Laravel Eloquent group results by relation
我正在努力让 Laravel Eloquent 以我喜欢的方式检索和分组结果。
基本上我正在创建一个 'My Agenda' 页面,它按截止日期的顺序显示所有任务,但如果 2 个或更多任务(按顺序)属于同一阶段,则将它们组合在一起,同样如果 2 个或更多阶段属于同一个项目。
我的数据是项目 ->(有很多)阶段 ->(有很多)任务
我想输出我的数据如下:
Project B
Stage 2
Task 1 (due 1st Sep)
Task 3 (due 2nd Sep)
Stage 1
Task 2 (due 3rd Sep)
Project A
Stage 1
Task 2 (due 4th Sep)
Project B <---- repeated as Project A has a stage->task due before these tasks due
Stage 3
Task 2 (due 5th Sep)
Project A <---- repeated as Project B has a stage->task due before
Stage 1 <---- repeated
Task 1 (due 6th Sep)
有什么办法可以实现吗?我愿意使用 JS/Vue/Lodash.
在前端执行此操作
提前致谢!
男
我认为你可以这样做:
首先,让我们用 JOIN 合并所有表。如果你想查看所有没有任何关系数据的项目和阶段,你可以使用 LEFT JOIN,或者 RIGHT JOIN,我不知道哪个有效。
$tasks = Task::orderBy("due")
->join("stages", "stages.id", "=", task.stage_id)
->join("projects", "projects.id", "=", stages.project_id)
->select("pick the columns you want to have")
->get();
我认为您应该将这种类型的数组作为输出,这样您就不会因为重复的键名而遇到任何问题。
/*
$output = [
[
'project'=> A,
'stages'=> [
stage_name => [task 1, task 2],
stage_name => [task 4, task 8],
],
],
[
'project'=> B,
'stages'=> [
stage_name => [task 5],
],
],
[...]
];
*/
要创建这种类型的数组,下面的函数应该可以工作。
$output = [];
foreach($tasks => $task) {
$project = $task['project_name'];
$lastEntry = $output[count($output) - 1];
if ( count($output) > 0 && $lastEntry['project'] == $project) {
// this means $task should be inserted in the last array.
// You should check for stages.
if (array_key_exists($task['stage_name'], $lastEntry['stages'])) {
$lastEntry['stages'][$task['stage_name']][] = $task;
} else {
$lastEntry['stages'][$task['stage_name']] = [$task];
}
// I think $lastEntry['stages'][$task['stage_name']][] = $task; will work without checking stage names, but I can't be sure, you need to try it.
} else {
// This means you should create a new item in $output.
$output[] = [
'project' => name,
'stages' => [
'stage_name' => [$task];
]
]
}
}
我直接在这里创建了那些代码。可以有错别字什么的,但逻辑应该是可行的。
我正在努力让 Laravel Eloquent 以我喜欢的方式检索和分组结果。
基本上我正在创建一个 'My Agenda' 页面,它按截止日期的顺序显示所有任务,但如果 2 个或更多任务(按顺序)属于同一阶段,则将它们组合在一起,同样如果 2 个或更多阶段属于同一个项目。
我的数据是项目 ->(有很多)阶段 ->(有很多)任务
我想输出我的数据如下:
Project B
Stage 2
Task 1 (due 1st Sep)
Task 3 (due 2nd Sep)
Stage 1
Task 2 (due 3rd Sep)
Project A
Stage 1
Task 2 (due 4th Sep)
Project B <---- repeated as Project A has a stage->task due before these tasks due
Stage 3
Task 2 (due 5th Sep)
Project A <---- repeated as Project B has a stage->task due before
Stage 1 <---- repeated
Task 1 (due 6th Sep)
有什么办法可以实现吗?我愿意使用 JS/Vue/Lodash.
在前端执行此操作提前致谢!
男
我认为你可以这样做:
首先,让我们用 JOIN 合并所有表。如果你想查看所有没有任何关系数据的项目和阶段,你可以使用 LEFT JOIN,或者 RIGHT JOIN,我不知道哪个有效。
$tasks = Task::orderBy("due")
->join("stages", "stages.id", "=", task.stage_id)
->join("projects", "projects.id", "=", stages.project_id)
->select("pick the columns you want to have")
->get();
我认为您应该将这种类型的数组作为输出,这样您就不会因为重复的键名而遇到任何问题。
/*
$output = [
[
'project'=> A,
'stages'=> [
stage_name => [task 1, task 2],
stage_name => [task 4, task 8],
],
],
[
'project'=> B,
'stages'=> [
stage_name => [task 5],
],
],
[...]
];
*/
要创建这种类型的数组,下面的函数应该可以工作。
$output = [];
foreach($tasks => $task) {
$project = $task['project_name'];
$lastEntry = $output[count($output) - 1];
if ( count($output) > 0 && $lastEntry['project'] == $project) {
// this means $task should be inserted in the last array.
// You should check for stages.
if (array_key_exists($task['stage_name'], $lastEntry['stages'])) {
$lastEntry['stages'][$task['stage_name']][] = $task;
} else {
$lastEntry['stages'][$task['stage_name']] = [$task];
}
// I think $lastEntry['stages'][$task['stage_name']][] = $task; will work without checking stage names, but I can't be sure, you need to try it.
} else {
// This means you should create a new item in $output.
$output[] = [
'project' => name,
'stages' => [
'stage_name' => [$task];
]
]
}
}
我直接在这里创建了那些代码。可以有错别字什么的,但逻辑应该是可行的。