Skip to content

Fix save() leaving the model dirty after a quiet save - #391

Merged
techmahedy merged 1 commit into
doppar:4.xfrom
techmahedy:issue
Oct 30, 2026
Merged

techmahedy merged 1 commit into
doppar:4.xfrom
techmahedy:issue

Conversation

@techmahedy

Copy link
Copy Markdown
Member

Pull Request Checklist

Q A
Branch? 4.x
Bug fix? yes
New feature? no
Deprecations? no
Issues -
License MIT

Description

$model->withoutHook()->save() wrote the row but left the model dirty. save() only synced originalAttributes inside the "hooks not suppressed" branch, so after a quiet save the model still treated the change as unsaved. update() already syncs unconditionally, so the two methods disagreed.

Impact

After a quiet save on the same instance:

  • getDirtyAttributes() and isDirtyAttr() still reported the persisted change, and getOriginal() returned the stale value.
  • The next plain save() with no new edits ran a second UPDATE and fired after_updated and the property watchers for a change that was already stored. The quiet save was meant to avoid exactly that, and the hook fired late and unexpectedly.

Changes

  • save() now syncs originalAttributes after every successful update. Only after_updated and the property watchers stay conditional on hooks not being suppressed.
  • The sync still runs after the hooks, so getOriginal() keeps returning the old value inside after_updated.
  • Added 13 tests in EntityModelHookTest and 1 in WatcherTest. They cover model state after a quiet save, the later plain save() (no re-fired hook, no rewritten row), suppression lasting one write only, other instances of the same row, hook ordering, parity with update(), and a property watch not firing late.

Backward Compatibility

Hook and watcher behavior is unchanged. The only difference is that a model is no longer reported dirty for a change that has already been written. Code that relied on the stale dirty state to re-save the same change would stop doing so, which is the intended fix.

Checklist

  • Tests have been added or updated
  • Documentation has been updated if necessary
  • Code follows the project coding standards
  • All tests pass locally

@techmahedy techmahedy added the bug Something isn't working label Oct 30, 2026
@techmahedy
techmahedy merged commit bb15c48 into doppar:4.x Oct 30, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant