Set up PHPUnit 11 inside docker-compose (PHP 8.2 CLI image with ext-mongodb)
and use red tests to drive three fixes in the ORM layer:
- MongoHydrator::dehydrate now recurses through EntityMap so #[Field(name)]
on embedded value objects is honoured symmetrically with hydrate.
dehydrateEmbedded was reading raw property names via ReflectionClass,
which silently broke round-trip when an embedded property had a renamed
field. See ADR-001.
- MongoHydrator::hydrate now resolves missing keys as: constructor default,
then nullable null, then LogicException with the field/class. Previously
every missing key became null, leaking as a TypeError from the entity
constructor for non-nullable typed properties.
- AbstractMongoRepository::persist detects new entities via the new
EntityMetadata::isNewId helper, which treats both '' and null as "new"
(was strict === '', so #[Id] ?string $id = null left null in the upsert
filter and could collide with other null-id documents).
EntityMap also makes #[Collection] optional for non-MongoEntity classes so
embedded value objects can declare #[Field]/#[Embedded] without owning a
Mongo collection.
Tests: 20 cases covering simple/embedded/embedded-list round-trip, BSON
inputs, missing-field semantics, EntityMap building rules, isNewId.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>