Skip to content

Commit 336ae3f

Browse files
authored
Merge pull request #7787 from kenjis/fix-Model-updateBatch
fix: [Model] updateBatch() may generate invalid SQL statement
2 parents 6dfc38b + 6b05c90 commit 336ae3f

2 files changed

Lines changed: 36 additions & 1 deletion

File tree

system/BaseModel.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,9 @@ public function updateBatch(?array $set = null, ?string $index = null, int $batc
979979
// properties representing the collection elements, we need to grab
980980
// them as an array.
981981
if (is_object($row) && ! $row instanceof stdClass) {
982-
$row = $this->objectToArray($row, true, true);
982+
// For updates the index field is needed even if it is not changed.
983+
// So set $onlyChanged to false.
984+
$row = $this->objectToArray($row, false, true);
983985
}
984986

985987
// If it's still a stdClass, go ahead and convert to
@@ -997,6 +999,13 @@ public function updateBatch(?array $set = null, ?string $index = null, int $batc
997999
// Save updateIndex for later
9981000
$updateIndex = $row[$index] ?? null;
9991001

1002+
if ($updateIndex === null) {
1003+
throw new InvalidArgumentException(
1004+
'The index ("' . $index . '") for updateBatch() is missing in the data: '
1005+
. json_encode($row)
1006+
);
1007+
}
1008+
10001009
// Must be called first so we don't
10011010
// strip out updated_at values.
10021011
$row = $this->doProtectFields($row);

tests/system/Models/UpdateModelTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,27 @@ public function testUpdateBatchSuccess(): void
147147
]);
148148
}
149149

150+
public function testUpdateBatchInvalidIndex(): void
151+
{
152+
$this->expectException(InvalidArgumentException::class);
153+
$this->expectExceptionMessage(
154+
'The index ("not_exist") for updateBatch() is missing in the data: {"name":"Derek Jones","country":"Greece"}'
155+
);
156+
157+
$data = [
158+
[
159+
'name' => 'Derek Jones',
160+
'country' => 'Greece',
161+
],
162+
[
163+
'name' => 'Ahmadinejad',
164+
'country' => 'Greece',
165+
],
166+
];
167+
168+
$this->createModel(UserModel::class)->updateBatch($data, 'not_exist');
169+
}
170+
150171
public function testUpdateBatchValidationFail(): void
151172
{
152173
$data = [
@@ -208,11 +229,16 @@ public function testUpdateBatchWithEntity(): void
208229
$entity1->name = 'Jones Martin';
209230
$entity1->country = 'India';
210231
$entity1->deleted = 0;
232+
$entity1->syncOriginal();
233+
// Update the entity.
234+
$entity1->country = 'China';
211235

236+
// This entity is not updated.
212237
$entity2->id = 4;
213238
$entity2->name = 'Jones Martin';
214239
$entity2->country = 'India';
215240
$entity2->deleted = 0;
241+
$entity2->syncOriginal();
216242

217243
$this->assertSame(2, $this->createModel(UserModel::class)->updateBatch([$entity1, $entity2], 'id'));
218244
}

0 commit comments

Comments
 (0)