Skip to content

fix: implement phase 1 ORM fixes#23

Merged
davebarnwell merged 3 commits intomainfrom
feature/phase-1-model-correctness
Mar 8, 2026
Merged

fix: implement phase 1 ORM fixes#23
davebarnwell merged 3 commits intomainfrom
feature/phase-1-model-correctness

Conversation

@davebarnwell
Copy link
Owner

Summary

This PR implements the Phase 1 roadmap work for the ORM and packages the roadmap itself into the repository so the next phases are explicit.

The user-visible effect is that several edge cases now fail predictably instead of leaking through as generic runtime or PDO failures. Model serialization also round-trips cleanly, zero-like primary keys no longer trigger accidental inserts, and dynamic finder helpers now define safe behavior for empty arrays.

The root cause was that the base model relied on a few permissive legacy behaviors: __sleep() exposed table field names instead of the actual internal state container, save() treated primary keys using truthiness rather than persistence semantics, unknown dynamic fields fell through to SQL generation, and empty array matches were allowed to drift toward invalid IN () queries. The library also surfaced generic Exception objects, which made it harder for calling code to handle failures precisely.

The fix introduces a small exception hierarchy under Freshsauce\\Model\\Exception, replaces the broken serialization path with __serialize() and __unserialize() while keeping __sleep() safe, changes persistence detection to treat any non-null primary key as existing state, makes unknown dynamic fields fail fast with a library exception, and short-circuits empty-array query helpers so they return [], null, or 0 as appropriate. The PR also adds SQLite-only helper models and regression tests that lock down zero-like custom primary keys, serialization, invalid dynamic field lookups, and empty-array matching behavior across the public helper surface.

The README now documents the exception behavior, and ROADMAP.md captures the phased follow-up work so future changes stay aligned with the package's lightweight scope.

Validation

I validated the changes with the existing quality gates:

  • vendor/bin/phpunit -c phpunit.xml.dist
  • vendor/bin/phpstan analyse -c phpstan.neon

@davebarnwell davebarnwell marked this pull request as ready for review March 8, 2026 08:36
Copilot AI review requested due to automatic review settings March 8, 2026 08:36
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements “Phase 1” ORM correctness/safety fixes by tightening error handling (new exception hierarchy), fixing serialization round-trips, correcting persisted-state detection for zero-like primary keys, and defining safe behavior for dynamic finders with unknown fields or empty match arrays.

Changes:

  • Introduces Freshsauce\Model\Exception\* exceptions and replaces several generic \Exception throws with model-specific failures.
  • Fixes model serialization by adding __serialize() / __unserialize() and making __sleep() safe.
  • Updates dynamic finders to fail fast on unknown fields and short-circuit empty-array matches to predictable empty/null/0 results; fixes save() to treat any non-null PK (including 0/'0') as persisted.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Model/Model.php Core ORM fixes: exception types, serialization support, PK persistence detection, dynamic finder field validation, and empty-match handling.
src/Model/Exception/ModelException.php Adds base ORM exception type.
src/Model/Exception/UnknownFieldException.php Adds dedicated exception for unknown fields.
src/Model/Exception/MissingDataException.php Adds dedicated exception for uninitialised model state access.
src/Model/Exception/InvalidDynamicMethodException.php Adds dedicated exception for invalid dynamic static methods.
src/Model/Exception/ConnectionException.php Adds dedicated exception for missing DB connection failures.
src/Model/Exception/ConfigurationException.php Adds dedicated exception for misconfiguration/driver/quoting failures.
tests/Model/CategoryTest.php Adds/updates regression tests for serialization round-trip, exception types, unknown dynamic field handling, and empty-array matcher behavior.
tests/Model/SqliteModelTest.php Adds SQLite regression tests for save() update behavior with zero-like custom primary keys.
test-src/Model/SqliteCodeCategory.php Adds SQLite helper model with integer custom PK for regression tests.
test-src/Model/SqliteStringCodeCategory.php Adds SQLite helper model with string custom PK for regression tests.
README.md Documents the new predictable exception behavior and links the roadmap.
ROADMAP.md Adds a phased roadmap describing the correctness work and follow-on plans.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@davebarnwell davebarnwell merged commit 51936a1 into main Mar 8, 2026
7 checks passed
@davebarnwell davebarnwell deleted the feature/phase-1-model-correctness branch March 8, 2026 08:53
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.

2 participants