Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 48 additions & 31 deletions system/BaseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -909,22 +909,7 @@ 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) {
$row = $this->objectToArray($row, false, true);
}

// If it's still a stdClass, go ahead and convert to
// an array so doProtectFields and other model methods
// don't have to do special checks.
if (is_object($row)) {
$row = (array) $row;
}

// Convert any Time instances to appropriate $dateFormat
$row = $this->timeToString($row);
$row = $this->transformDataRowToArray($row);

// Validate every row.
if (! $this->skipValidation && ! $this->validate($row)) {
Expand Down Expand Up @@ -1051,21 +1036,7 @@ 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) {
// For updates the index field is needed even if it is not changed.
// So set $onlyChanged to false.
$row = $this->objectToArray($row, false, true);
}

// If it's still a stdClass, go ahead and convert to
// an array so doProtectFields and other model methods
// don't have to do special checks.
if (is_object($row)) {
$row = (array) $row;
}
$row = $this->transformDataRowToArray($row);

// Validate data before saving.
if (! $this->skipValidation && ! $this->validate($row)) {
Expand Down Expand Up @@ -1696,6 +1667,52 @@ protected function trigger(string $event, array $eventData)
return $eventData;
}

/**
* If the model is using casts, this will convert the data
* in $row according to the rules defined in `$casts`.
*
* @param object|row_array|null $row Row data
*
* @return object|row_array|null Converted row data
*
* @used-by insertBatch()
* @used-by updateBatch()
*
* @throws ReflectionException
* @deprecated Since 4.6.4, temporary solution - will be removed in 4.7
*/
protected function transformDataRowToArray(array|object|null $row): array|object|null
{
// 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);
}

// If it's still a stdClass, go ahead and convert to
// an array so doProtectFields and other model methods
// don't have to do special checks.
if (is_object($row)) {
$row = (array) $row;
}

// Convert any Time instances to appropriate $dateFormat
return $this->timeToString($row);
}

/**
* Sets the return type of the results to be as an associative array.
*
Expand Down
31 changes: 31 additions & 0 deletions tests/system/Models/InsertModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 @@ public function testInsertWithDefaultValue(): void
$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); // @phpstan-ignore argument.type

$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'); // @phpstan-ignore argument.type
$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
Loading