diff --git a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php index 1654e39b12b7..7fbc524fad8d 100644 --- a/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php +++ b/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php @@ -960,11 +960,8 @@ public function getDirty() { $dirty = []; - foreach ($this->attributes as $key => $value) { - if (! array_key_exists($key, $this->original)) { - $dirty[$key] = $value; - } elseif ($value !== $this->original[$key] && - ! $this->originalIsNumericallyEquivalent($key)) { + foreach ($this->getAttributes() as $key => $value) { + if (! $this->originalIsEquivalent($key, $value)) { $dirty[$key] = $value; } } @@ -973,16 +970,35 @@ public function getDirty() } /** - * Determine if the new and old values for a given key are numerically equivalent. + * Determine if the new and old values for a given key are equivalent. * - * @param string $key + * @param string $key + * @param mixed $current * @return bool */ - protected function originalIsNumericallyEquivalent($key) + protected function originalIsEquivalent($key, $current) { - $current = $this->attributes[$key]; + if (! array_key_exists($key, $this->original)) { + return false; + } - $original = $this->original[$key]; + if ($current === $original = $this->getOriginal($key)) { + return true; + } + + // When check rich this check and current attribute value not equals with original, we should skip next steps + // if current is null + if (is_null($current)) { + return false; + } + + if ($this->isDateAttribute($key)) { + return $this->fromDateTime($current) === $this->fromDateTime($original); + } + + if ($this->hasCast($key)) { + return $this->castAttribute($key, $current) === $this->castAttribute($key, $original); + } // This method checks if the two values are numerically equivalent even if they // are different types. This is in case the two values are not the same type diff --git a/tests/Database/DatabaseEloquentModelTest.php b/tests/Database/DatabaseEloquentModelTest.php index b80546a87351..51c563e7dfac 100755 --- a/tests/Database/DatabaseEloquentModelTest.php +++ b/tests/Database/DatabaseEloquentModelTest.php @@ -67,6 +67,31 @@ public function testDirtyAttributes() $this->assertTrue($model->isDirty(['foo', 'bar'])); } + public function testDirtyOnCastOrDateAttributes() + { + $model = new EloquentModelCastingStub; + $model->setDateFormat('Y-m-d H:i:s'); + $model->boolAttribute = 1; + $model->foo = 1; + $model->bar = '2017-03-18'; + $model->dateAttribute = '2017-03-18'; + $model->datetimeAttribute = '2017-03-23 22:17:00'; + $model->syncOriginal(); + + $model->boolAttribute = true; + $model->foo = true; + $model->bar = '2017-03-18 00:00:00'; + $model->dateAttribute = '2017-03-18 00:00:00'; + $model->datetimeAttribute = null; + + $this->assertTrue($model->isDirty()); + $this->assertTrue($model->isDirty('foo')); + $this->assertTrue($model->isDirty('bar')); + $this->assertFalse($model->isDirty('boolAttribute')); + $this->assertFalse($model->isDirty('dateAttribute')); + $this->assertTrue($model->isDirty('datetimeAttribute')); + } + public function testCleanAttributes() { $model = new EloquentModelStub(['foo' => '1', 'bar' => 2, 'baz' => 3]);