Skip to content

Commit

Permalink
feat: add option $updateOnlyChanged to BaseModel
Browse files Browse the repository at this point in the history
  • Loading branch information
kenjis committed Jan 25, 2024
1 parent 5863eb3 commit cbee64b
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 2 deletions.
15 changes: 13 additions & 2 deletions system/BaseModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ abstract class BaseModel
*/
protected bool $allowEmptyInserts = false;

/**
* Whether to update Entity's only changed data.
*/
protected bool $updateOnlyChanged = true;

/**
* Rules used to validate data in insert, update, and save methods.
* The array must match the format of data passed to the Validation
Expand Down Expand Up @@ -1794,9 +1799,15 @@ protected function transformDataToArray($row, string $type): array
// properties representing the collection elements, we need to grab
// them as an array.
if (is_object($row) && ! $row instanceof stdClass) {
if ($type === 'update' && ! $this->updateOnlyChanged) {
$onlyChanged = false;
}
// If it validates with entire rules, all fields are needed.
$onlyChanged = ($this->skipValidation === false && $this->cleanValidationRules === false)
? false : ($type === 'update');
elseif ($this->skipValidation === false && $this->cleanValidationRules === false) {
$onlyChanged = false;
} else {
$onlyChanged = ($type === 'update');
}

$row = $this->objectToArray($row, $onlyChanged, true);
}
Expand Down
2 changes: 2 additions & 0 deletions system/Commands/Generators/Views/model.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ class {class} extends Model
protected $protectFields = true;
protected $allowedFields = [];

protected bool $updateOnlyChanged = true;

// Dates
protected $useTimestamps = false;
protected $dateFormat = 'datetime';
Expand Down
22 changes: 22 additions & 0 deletions tests/system/Models/UpdateModelTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
use Config\Database;
use InvalidArgumentException;
use stdClass;
use Tests\Support\Entity\User;
use Tests\Support\Entity\UUID;
use Tests\Support\Models\EventModel;
use Tests\Support\Models\JobModel;
use Tests\Support\Models\SecondaryModel;
use Tests\Support\Models\UserModel;
use Tests\Support\Models\UserTimestampModel;
use Tests\Support\Models\UUIDPkeyModel;
use Tests\Support\Models\ValidModel;
use Tests\Support\Models\WithoutAutoIncrementModel;
Expand Down Expand Up @@ -535,4 +537,24 @@ public static function provideUpdateThrowDatabaseExceptionWithoutWhereClause():
],
];
}

public function testUpdateEntityUpdateOnlyChangedFalse(): void
{
$model = new class () extends UserTimestampModel {
protected $returnType = User::class;
protected bool $updateOnlyChanged = false;
};

$user = $model->find(1);
$updateAtBefore = $user->updated_at;

// updates the Entity without changes.
$result = $model->update(1, $user);

$user = $model->find(1);
$updateAtAfter = $user->updated_at;

$this->assertTrue($result);
$this->assertNotSame($updateAtBefore, $updateAtAfter);
}
}
10 changes: 10 additions & 0 deletions user_guide_src/source/models/model.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,16 @@ potential mass assignment vulnerabilities.

.. note:: The `$primaryKey`_ field should never be an allowed field.

$updateOnlyChanged
------------------

.. versionadded:: 4.5.0

Whether to update :doc:`Entity <./entities>`'s only changed fields. The default
value is ``true``, meaning that only changed field data is used when updating.
So if you try to update an Entity without changes, an exception with
"There is no data to update." will raise.

Dates
-----

Expand Down
2 changes: 2 additions & 0 deletions user_guide_src/source/models/model/005.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class UserModel extends Model

protected $allowedFields = ['name', 'email'];

protected bool $updateOnlyChanged = true;

// Dates
protected $useTimestamps = false;
protected $dateFormat = 'datetime';
Expand Down

0 comments on commit cbee64b

Please sign in to comment.