Skip to content

Version 7.0: observers driven by the anydataset-db DatabaseExecutor#33

Open
byjg wants to merge 1 commit into
masterfrom
7.0
Open

Version 7.0: observers driven by the anydataset-db DatabaseExecutor#33
byjg wants to merge 1 commit into
masterfrom
7.0

Conversation

@byjg

@byjg byjg commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

Version 7.0 rewires the entire observer system on top of the low-level DatabaseExecutor observer from byjg/anydataset-db 7.0, and migrates off the driver query methods removed in that release.

  • ORMSubject removed: dispatch now flows through ObserverBridge, a DatabaseEventObserverInterface implementation attached one-per-DatabaseExecutor (tracked in a WeakMap — no global state, nothing to clear in tests)
  • Complete coverage: every write built by MicroOrm notifies — save(), delete(), deleteByQuery(), bulkExecute() (after commit, nothing on rollback), buildAndExecute(), and built statements executed directly on the executor
  • Same semantics for save(): deferred dispatch keeps notifying after key rehydration, so Insert observers still receive the entity with its generated PK
  • OrmSqlStatement: every builder build() returns it, stamped with the ORM event and affected table; exposed to observers via ObserverData::getStatement()
  • New ObserverEvent::SoftDelete: soft deletes now fire an event (previously silent)
  • New StatementHookInterface: before-execute hook with full SQL/params access; throwing vetoes the write
  • Raw observer passthrough: Repository::addObserver() also accepts a raw DatabaseEventObserverInterface; new removeObserver()
  • Performance: zero observers → zero cost (no singleton call per write anymore); non-matching tables exit on a single hash check; no new SELECTs

ObserverProcessorInterface implementations require no code change. Breaking changes and the migration table are documented in CHANGELOG-7.0.md.

Breaking changes

  • ORMSubject removed (including clearObservers())
  • Observer scope changed from global to per-executor: repositories on different DatabaseExecutor instances no longer cross-notify
  • More events fire than before (SoftDelete, bulk, direct executions)
  • Repository protected helpers insert()/insertWithAutoInc()/insertWithKeyGen()/update() now receive the pre-built OrmSqlStatement
  • Requires byjg/anydataset-db: ^7.0 (driver query methods removed upstream)

Test plan

  • All 5 pre-existing observer tests pass with unchanged assertions (semantic gate, including generated-id visibility on insert)
  • 10 new tests in tests/ObserverBridgeTest.php: soft delete event, direct executor writes, bulk commit/rollback, per-executor scoping, veto hook, getStatement(), raw passthrough, addDbDriverForWrite() re-attach, onError() swallowing
  • Full suite: 336 tests, 1012 assertions, green against anydataset-db 7.0.x-dev; Psalm clean

…erver

- Remove the global ORMSubject singleton; observer dispatch now flows
  through ObserverBridge, a DatabaseEventObserverInterface implementation
  attached per DatabaseExecutor
- Query builders return OrmSqlStatement (extends SqlStatement) stamped
  with the ORM event and affected table
- All writes now notify: save(), delete(), deleteByQuery(), bulkExecute()
  (after commit), buildAndExecute() and built statements executed directly
  on the executor
- save() keeps its previous semantics via deferred dispatch: observers
  receive the entity rehydrated with generated keys
- New ObserverEvent::SoftDelete case: soft deletes now fire an event
- New StatementHookInterface: before-execute hook with veto (throwing
  aborts the write)
- Repository::addObserver() also accepts raw DatabaseEventObserverInterface;
  new Repository::removeObserver(); addDbDriverForWrite() re-attaches
  observers to the new write executor
- ObserverData::getStatement() exposes the SQL statement to observers
- Require byjg/anydataset-db ^7.0 and migrate tests/docs off the driver
  query methods removed in that release
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant