pmill/doctrine-array-hydrator
pmill/doctrine-array-hydrator provides a Doctrine hydrator that populates entities and embedded objects from plain arrays, including nested associations and collections. It is useful for fixtures, imports, and API payloads, simplifying conversion of array data into Doctrine entities.
Architecture fit. pmill/doctrine-array-hydrator is a narrow, framework-agnostic utility for the Doctrine ORM: it maps associative arrays onto entity objects using Doctrine's class metadata rather than a full serializer. That makes it a fit only for Laravel estates that have already adopted Doctrine via laravel-doctrine (or a comparable integration) — the majority Eloquent-first Laravel codebases get no value here. Where Doctrine is in place, the natural slot is the inbound ingestion boundary: CSV/JSON imports, webhook payloads, ERP/CRM syncs, legacy data migrations, and fixture seeding, where you want an array turned into a managed entity without hand-writing setters for every field. It is explicitly not a replacement for Symfony Serializer, JMS Serializer, or API Platform's denormalization layer, and should not become the app-wide DTO strategy.
Integration feasibility. Low friction to try: Composer-installable, MIT-licensed, small API surface, no service provider or config to wire in Laravel. The real work is verification, not integration — confirm the composer.json constraints against your PHP and doctrine/orm versions, confirm whether it uses annotations versus PHP 8 attributes, and confirm behavior for typed properties, enums, DateTimeImmutable, embeddables, and collections. A one-day spike against a representative entity is enough to reach a go/no-go.
Technical risk. This is the dominant concern. Last release was January 2020, and 35 stars implies a single-maintainer project with a bus factor of one. Six years of drift spans PHP 8.0–8.4 (typed properties, enums, readonly, union types) and Doctrine ORM 2.x → 3.x (annotation driver removal, metadata API changes). Expect at least some breakage, and assume you will own the patches. Secondary risks: hydration likely bypasses setters and domain invariants, may not fire lifecycle callbacks or validation, and — if it maps array keys to entity fields without an allowlist — introduces an over-posting/mass-assignment exposure that must be constrained at the call site. Silent partial hydration (unknown keys ignored, missing keys defaulted) is the failure mode most likely to produce corrupt records quietly.
Key questions.
Stack fit. Gate on Doctrine: viable only where doctrine/orm is a first-class persistence layer. Treat it as an internal adapter inside the ingestion pipeline — one class behind your own EntityHydrator interface — never as a public API for controllers or domain services.
Migration path. No schema or data migration is required; this is additive. Introduce it behind the interface, land it on a single importer, and keep the existing hand-written mapper in place until the pilot passes contract tests. That preserves a one-line rollback and makes a later swap to Symfony Serializer or a hand-rolled mapper a non-event.
Compatibility. Pin exact constraints in composer.json, add the package to your dependency-audit and licence inventory, and run it through PHPStan/Larastan plus a CI matrix across your supported PHP and Doctrine versions. Watch for Doctrine deprecation notices on every ORM upgrade — that is your early-warning signal.
Sequencing.
DateTimeImmutable, and an embeddable.Maintenance. Effectively self-maintained. The codebase is small enough that forking is cheaper than lobbying upstream; the cost is a standing obligation to patch for each PHP and Doctrine major. Assign explicit ownership — an unowned fork rots faster than the abandoned original.
Support. Community-only, no vendor, no SLA, no security advisory pipeline. Escalation path is "read the source," which is feasible here because of the small surface. Do not place it on any path where a CVE or a PHP upgrade would block a release unplanned.
Scaling. Hydration is reflection-driven CPU work, adequate for batch imports in the thousands. For larger volumes, chunk the input, flush and clear() the EntityManager between batches, and watch memory when arrays carry nested collections. It has no place on a hot request path — keep it in queue workers and console commands.
Failure modes. Ranked by blast radius: (1) silent partial hydration — unknown keys dropped, required fields defaulted, records written incomplete; mitigate with strict-mode tests and post-hydration validation; (2) over-posting — attacker-controlled array keys reaching unintended entity fields; mitigate with per-entity allowlists; (3) type drift — string-to-DateTime, int/float coercion, enum backing values; (4) association mishandling — duplicate or orphaned related rows on repeated imports; (5) bypassed invariants — setters, lifecycle callbacks, and audit listeners skipped, so validation must run explicitly before flush(). Add a reconciliation count on every import job so silent loss is detected rather than discovered downstream.
Ramp-up. Half a day for a developer already fluent in Doctrine metadata and the UnitOfWork; one to two days if custom hydration is needed for enums or value objects. The scarce skill is Doctrine familiarity, not this package — factor that into team composition before adopting.
How can I help you explore Laravel packages today?