Eloquent 的 createMany 方法是否保留输入数组顺序?
Does Eloquent's createMany method preserves the input array order?
我有 Choice
型号 belongTo Question
型号 belongTo Quiz
型号。确切地说:
- 一个
Quiz
正好有4个questions
.
- A
Question
刚好有 4 choices
.
上述关系在 Request
中很受欢迎(如下所示)。
我需要在三个事务中完成所有插入操作。
我有以下两个成功的交易。
DB::transaction(function () use ($request) {
$quiz = Quiz::create(['start_at' => $request->start_at, 'duration' => $request->duration]);
$questions = $quiz->questions()->createMany($request->questions);
// ...
现在我需要确认 $questions
将类似于 $request->questions
在任何情况下都按照数据的顺序,依靠这一事实并将id
从返回的集合映射到Request
的选择作为foreign ids 并再做一次批量插入。
// ...
$choices = [];
foreach ($request->questions as $i => $question_data) {
foreach ($question_data['choices'] as $j => $choice_content) {
$choices[] = [
'question_id' => $questions[$i - 1]->id, // Append foreign id
'content' => $choice_content,
'choice_number' => $j,
'is_correct' => $j == $question_data['is_correct'],
'created_at' => date('Y-m-d H:i:s'),
];
}
}
Choice::insert($choices);
});
{
"start_at": "2022-07-17T19:54",
"duration": "191",
"questions": {
"1": {
"content": "Sed asperiores eaque voluptatem id saepe.",
"choices": {
"1": "Ad quia impedit libero voluptatem qui.",
"2": "Voluptates quis consequuntur natus illum laborum tempore.",
"3": "Corrupti dolorum optio quam qui.",
"4": "Numquam quidem voluptatem nisi."
},
"is_correct": "4"
},
"2": {
"content": "Illum ut tempora.",
"choices": {
"1": "Consequatur minima tempora qui amet.",
"2": "Voluptate sint sapiente illum delectus possimus enim.",
"3": "A magni aut aperiam aliquam laboriosam.",
"4": "Faustino MacGyver"
},
"is_correct": "4"
},
"3": {
// ...
},
"4": {
// ...
}
}
}
获取生成的SQL。如果末尾附近有一个 ORDER BY
子句,那么顺序是可预测的。如果没有 ORDER BY
子句,数据库可以自由地以任何顺序传送结果。
Laravel 的 createMany
在您提供的数组上执行 foreach
并按照您传入的顺序执行 returns 它应该保留命令。
这是来源:
public function createMany(iterable $records)
{
$instances = $this->related->newCollection();
foreach ($records as $record) {
$instances->push($this->create($record));
}
return $instances;
}
这不一定适用于该数据的后续查询。这取决于数据库如何决定在没有 order by 子句的情况下对其进行排序。
话虽如此,您可以通过在创建每个问题时设置选项来避免整个问题。由于你们有关系,您可以允许 Laravel 弄清楚如何设置正确的 ID。
foreach ($request->questions as $question_data) {
$question = $quiz->questions()->create([
// question data here
]);
foreach ($question_data['choices'] as $j => $choice_content) {
$question->choices()->create(
[
// choice data here
]
);
}
}
我有 Choice
型号 belongTo Question
型号 belongTo Quiz
型号。确切地说:
- 一个
Quiz
正好有4个questions
. - A
Question
刚好有 4choices
.
上述关系在 Request
中很受欢迎(如下所示)。
我需要在三个事务中完成所有插入操作。
我有以下两个成功的交易。
DB::transaction(function () use ($request) {
$quiz = Quiz::create(['start_at' => $request->start_at, 'duration' => $request->duration]);
$questions = $quiz->questions()->createMany($request->questions);
// ...
现在我需要确认 $questions
将类似于 $request->questions
在任何情况下都按照数据的顺序,依靠这一事实并将id
从返回的集合映射到Request
的选择作为foreign ids 并再做一次批量插入。
// ...
$choices = [];
foreach ($request->questions as $i => $question_data) {
foreach ($question_data['choices'] as $j => $choice_content) {
$choices[] = [
'question_id' => $questions[$i - 1]->id, // Append foreign id
'content' => $choice_content,
'choice_number' => $j,
'is_correct' => $j == $question_data['is_correct'],
'created_at' => date('Y-m-d H:i:s'),
];
}
}
Choice::insert($choices);
});
{
"start_at": "2022-07-17T19:54",
"duration": "191",
"questions": {
"1": {
"content": "Sed asperiores eaque voluptatem id saepe.",
"choices": {
"1": "Ad quia impedit libero voluptatem qui.",
"2": "Voluptates quis consequuntur natus illum laborum tempore.",
"3": "Corrupti dolorum optio quam qui.",
"4": "Numquam quidem voluptatem nisi."
},
"is_correct": "4"
},
"2": {
"content": "Illum ut tempora.",
"choices": {
"1": "Consequatur minima tempora qui amet.",
"2": "Voluptate sint sapiente illum delectus possimus enim.",
"3": "A magni aut aperiam aliquam laboriosam.",
"4": "Faustino MacGyver"
},
"is_correct": "4"
},
"3": {
// ...
},
"4": {
// ...
}
}
}
获取生成的SQL。如果末尾附近有一个 ORDER BY
子句,那么顺序是可预测的。如果没有 ORDER BY
子句,数据库可以自由地以任何顺序传送结果。
Laravel 的 createMany
在您提供的数组上执行 foreach
并按照您传入的顺序执行 returns 它应该保留命令。
这是来源:
public function createMany(iterable $records)
{
$instances = $this->related->newCollection();
foreach ($records as $record) {
$instances->push($this->create($record));
}
return $instances;
}
这不一定适用于该数据的后续查询。这取决于数据库如何决定在没有 order by 子句的情况下对其进行排序。
话虽如此,您可以通过在创建每个问题时设置选项来避免整个问题。由于你们有关系,您可以允许 Laravel 弄清楚如何设置正确的 ID。
foreach ($request->questions as $question_data) {
$question = $quiz->questions()->create([
// question data here
]);
foreach ($question_data['choices'] as $j => $choice_content) {
$question->choices()->create(
[
// choice data here
]
);
}
}