Skip to content

Commit fd6a5b2

Browse files
author
Pantea Marius-ciclistu
committed
POC for laravel/framework#31778 improve getDirty calls laravel/framework#57627
1 parent aeeb541 commit fd6a5b2

File tree

2 files changed

+27
-9
lines changed

2 files changed

+27
-9
lines changed

illuminate/Database/Eloquent/Concerns/HasAttributes.php

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ trait HasAttributes
6464
*/
6565
protected $changes = [];
6666

67+
/**
68+
* Temporary cache to avoid multiple getDirty calls generating multiple set calls for
69+
* sync/merge casted attributes to objects to persist the possible changes made to those objects
70+
*/
71+
protected ?array $tmpDirtyCache = null;
72+
6773
/**
6874
* The attributes that should be cast.
6975
*
@@ -2041,10 +2047,7 @@ public function syncChanges()
20412047
*/
20422048
public function isDirty($attributes = null)
20432049
{
2044-
return $this->hasChanges(
2045-
$this->getDirty(),
2046-
is_array($attributes) ? $attributes : func_get_args()
2047-
);
2050+
return [] !== $this->getDirty(\is_array($attributes) ? $attributes : \func_get_args());
20482051
}
20492052

20502053
/**
@@ -2114,14 +2117,27 @@ protected function hasChanges($changes, $attributes = null)
21142117

21152118
/**
21162119
* Get the attributes that have been changed since the last sync.
2117-
*
2120+
* @param string|array $attributes
21182121
* @return array
21192122
*/
21202123
public function getDirty()
21212124
{
2125+
if (isset($this->tmpDirtyCache)) {
2126+
if ([] !== $args = \func_get_args()) {
2127+
return \array_intersect_key($this->tmpDirtyCache, \array_flip((array)$args[0]));
2128+
}
2129+
2130+
return $this->tmpDirtyCache;
2131+
}
2132+
2133+
$attributes = (array)(\func_get_args()[0] ?? \array_keys($this->attributes));
2134+
21222135
$dirty = [];
21232136

2124-
foreach ($this->getAttributes() as $key => $value) {
2137+
foreach ($attributes as $key) {
2138+
// this will merge/sync before the if condition
2139+
$value = $this->getAttributeFromArray($key);
2140+
21252141
if (!$this->originalIsEquivalent($key)) {
21262142
$dirty[$key] = $value;
21272143
}

illuminate/Database/Eloquent/Model.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ function () use ($column) {
995995

996996
$this->fireModelEvent('updated', false);
997997

998-
$this->syncOriginalAttribute($column);
998+
$this->syncOriginalAttributes(\array_keys($this->changes));
999999
}
10001000
);
10011001
}
@@ -1232,12 +1232,14 @@ protected function performUpdate(Builder $query)
12321232
// Once we have run the update operation, we will fire the "updated" event for
12331233
// this model instance. This will allow developers to hook into these after
12341234
// models are updated, giving them a chance to do any special processing.
1235+
// this is needed because updating event might change the model
12351236
$dirty = $this->getDirtyForUpdate();
12361237

1237-
if (count($dirty) > 0) {
1238+
if ([] !== $dirty) {
12381239
$this->setKeysForSaveQuery($query)->update($dirty);
1239-
1240+
$this->tmpDirtyCache = $dirty;
12401241
$this->syncChanges();
1242+
unset($this->tmpDirtyCache);
12411243

12421244
$this->fireModelEvent('updated', false);
12431245
}

0 commit comments

Comments
 (0)