Skip to content
41 changes: 33 additions & 8 deletions system/BaseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -909,10 +909,22 @@ public function insertBatch(?array $set = null, ?bool $escape = null, int $batch

if (is_array($set)) {
foreach ($set as &$row) {
// If $row is using a custom class with public or protected
// properties representing the collection elements, we need to grab
// them as an array.
if (is_object($row) && ! $row instanceof stdClass) {
// If casts are used, convert the data first
if ($this->useCasts()) {
if (is_array($row)) {
$row = $this->converter->toDataSource($row);
} elseif ($row instanceof stdClass) {
$row = (array) $row;
$row = $this->converter->toDataSource($row);
} elseif ($row instanceof Entity) {
$row = $this->converter->extract($row);
} elseif (is_object($row)) {
$row = $this->converter->extract($row);
}
} elseif (is_object($row) && ! $row instanceof stdClass) {
// If $row is using a custom class with public or protected
// properties representing the collection elements, we need to grab
// them as an array.
$row = $this->objectToArray($row, false, true);
}

Expand Down Expand Up @@ -1051,10 +1063,23 @@ public function updateBatch(?array $set = null, ?string $index = null, int $batc
{
if (is_array($set)) {
foreach ($set as &$row) {
// If $row is using a custom class with public or protected
// properties representing the collection elements, we need to grab
// them as an array.
if (is_object($row) && ! $row instanceof stdClass) {
// If casts are used, convert the data first
if ($this->useCasts()) {
if (is_array($row)) {
$row = $this->converter->toDataSource($row);
} elseif ($row instanceof stdClass) {
$row = (array) $row;
$row = $this->converter->toDataSource($row);
} elseif ($row instanceof Entity) {
$row = $this->converter->extract($row);
} elseif (is_object($row)) {
$row = $this->converter->extract($row);
}
} elseif (is_object($row) && ! $row instanceof stdClass) {
// If $row is using a custom class with public or protected
// properties representing the collection elements, we need to grab
// them as an array.

// For updates the index field is needed even if it is not changed.
// So set $onlyChanged to false.
$row = $this->objectToArray($row, false, true);
Expand Down
31 changes: 31 additions & 0 deletions tests/system/Models/InsertModelTest.php
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<?php

declare(strict_types=1);
Expand All @@ -22,6 +22,7 @@
use stdClass;
use Tests\Support\Entity\User;
use Tests\Support\Models\JobModel;
use Tests\Support\Models\UserCastsTimestampModel;
use Tests\Support\Models\UserModel;
use Tests\Support\Models\UserObjModel;
use Tests\Support\Models\WithoutAutoIncrementModel;
Expand Down Expand Up @@ -376,4 +377,34 @@
$id = $this->model->getInsertID();
$this->assertSame($entity->country, $this->model->find($id)->country);
}

public function testInsertBatchWithCasts(): void
{
$userData = [
[
'name' => 'Smriti',
'email' => [
'personal' => '[email protected]',
'work' => '[email protected]',
],
'country' => 'India',
],
[
'name' => 'Rahul',
'email' => [
'personal' => '[email protected]',
'work' => '[email protected]',
],
'country' => 'India',
],
];
$this->createModel(UserCastsTimestampModel::class);

$numRows = $this->model->insertBatch($userData);

$this->assertSame(2, $numRows);

$this->seeInDatabase('user', ['email' => json_encode($userData[0]['email'])]);
$this->seeInDatabase('user', ['email' => json_encode($userData[1]['email'])]);
}
}
40 changes: 40 additions & 0 deletions tests/system/Models/UpdateModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use Tests\Support\Models\EventModel;
use Tests\Support\Models\JobModel;
use Tests\Support\Models\SecondaryModel;
use Tests\Support\Models\UserCastsTimestampModel;
use Tests\Support\Models\UserModel;
use Tests\Support\Models\UserTimestampModel;
use Tests\Support\Models\UUIDPkeyModel;
Expand Down Expand Up @@ -602,4 +603,43 @@ public function testUpdateEntityUpdateOnlyChangedFalse(): void
$this->assertTrue($result);
$this->assertNotSame($updateAtBefore, $updateAtAfter);
}

public function testUpdateBatchWithCasts(): void
{
$this->createModel(UserCastsTimestampModel::class);

$rows = $this->db->table('user')->limit(2)->orderBy('id', 'asc')->get()->getResultArray();

$this->assertNotEmpty($rows);
$this->assertCount(2, $rows);

$row1 = $rows[0];
$row2 = $rows[1];

$this->assertNotNull($row1);
$this->assertNotNull($row2);

$updateData = [
[
'id' => $row1['id'],
'email' => [
'personal' => '[email protected]',
'work' => '[email protected]',
],
],
[
'id' => $row2['id'],
'email' => [
'personal' => '[email protected]',
'work' => '[email protected]',
],
],
];

$numRows = $this->model->updateBatch($updateData, 'id');
$this->assertSame(2, $numRows);

$this->seeInDatabase('user', ['email' => json_encode($updateData[0]['email'])]);
$this->seeInDatabase('user', ['email' => json_encode($updateData[1]['email'])]);
}
}
1 change: 1 addition & 0 deletions user_guide_src/source/changelogs/v4.6.4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Bugs Fixed
- **Database:** Fixed a bug in ``Connection::getFieldData()`` for ``SQLSRV`` and ``OCI8`` where extra characters were returned in column default values (specific to those handlers), instead of following the convention used by other drivers.
- **Forge:** Fixed a bug in ``Postgre`` and ``SQLSRV`` where changing a column's default value using ``Forge::modifyColumn()`` method produced incorrect SQL syntax.
- **Model:** Fixed a bug in ``Model::replace()`` where ``created_at`` field (when available) wasn't set correctly.
- **Model:** Fixed a bug in ``Model::insertBatch()`` and ``Model::updateBatch()`` where casts were not applied to inserted or updated values.

See the repo's
`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_
Expand Down
Loading