Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Generated Hydrator Laravel Package

ocramius/generated-hydrator

Generates fast, specialized hydrator classes for PHP objects, letting you populate and extract properties quickly without reflection overhead. A good fit for ORMs, serializers, and data mappers.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What it actually does. ocramius/generated-hydrator is a compile-time code-generation tool for object hydration. At runtime it reflects once on a target class, generates a dedicated PHP hydrator class into a cache directory, and then includes that class so that hydration and extraction become direct property writes rather than repeated reflection or setter calls. The generation cost is paid once per class per deployment; the hydration cost then approaches a hand-written mapper. Core runtime dependency is laminas/laminas-code (legacy path: zend-code); there is no Laravel binding, config file, facade, or service provider.

Architecture fit. This is infrastructure, not domain code. It belongs behind a port at the persistence/serialization boundary — read-model DTOs, bulk imports, CSV/report exports, ETL jobs, and queue-payload rehydration. It is a poor fit anywhere near Eloquent: hydrate() writes to non-public properties directly, so $fillable mass-assignment protection, casts, mutators, observers, timestamps, and validation do not run. Teams that treat this as a faster Model::hydrate() will silently bypass the framework's guardrails. It should be adopted only for objects that are pure data carriers with no framework semantics attached.

Integration feasibility. Technically straightforward — one configuration object (target directory, autoloader) bound as a singleton, one factory reused for hydrator instances. Roughly a sprint-day of glue code. The real cost is not wiring; it is that with zero dependents in the scanned ecosystem there is no reference integration, no community glue, and no prior art to benchmark against. Every pattern is bespoke and must be reviewed and tested internally.

Technical risk (ranked).

  1. Archived status is a hard risk, not a caveat. Last release January 2024, no maintainer, no security advisory channel, no PHP 8.4/8.5 support path. This package generates PHP source code; any upstream syntax or deprecation change is a break with no fix coming.
  2. Framework guard bypass. Direct property injection means validation and authorization must be provably upstream of the hydrator. This is an architectural correctness risk, not just a hygiene one.
  3. Runtime codegen touching disk. Writable filesystem requirements, OPcache interactions, and multi-container cold-start behavior are operational hazards that surface in production, not in dev.
  4. Diminishing value proposition. PHP 8 Closure::bind-based hydration ((fn() => $this->x = $y)->call($obj)) delivers most of the speedup with no codegen, no cache directory, and no dependency. The package's core advantage has eroded since it was designed.

Key questions before commitment.

  • Which Laravel/PHP minor versions are actually declared in composer.json, and does that cover our target runtime for the next 18 months?
  • How does it behave with readonly properties, promoted constructor properties, enums, and uninitialized typed properties — does it fatal or silently skip?
  • Do we have a measured, production-representative benchmark showing the win over Model::hydrate(), symfony/serializer, or bounded-closure hydration at our object counts?
  • Who owns the fork when it breaks, and what is the monthly budget for that ownership?
  • Can every call site prove that input was validated before hydration?

Integration Approach

Stack fit. Workable on Laravel 10/11 with PHP 8.1+, contingent on verifying the composer constraint actually admits the runtime we ship on — for an archived package this is the first gate, not a formality. Wire it as a singleton factory in a dedicated service provider with the target directory at storage/app/generated-hydrators (gitignored). No config publishing exists; keep the config inside our own config/ file so it is cacheable with config:cache.

Migration path. Do not retrofit. Introduce a single internal interface — ObjectHydrator with hydrate(object $o, array $data): object and extract(object $o): array — with a GeneratedHydratorAdapter behind it. That port is the entire insurance policy: if the package is retired, we swap one class. If replacing an existing serializer, run both implementations behind a feature flag on one read path, diff the outputs, and only then cut over. Never let application code type-hint against GeneratedHydrator\* directly.

Compatibility. Build an explicit compatibility test matrix before adoption rather than discovering semantics in production: readonly properties, uninitialized typed properties with missing array keys, enums, nested objects (does it recurse?), __get/__set, and private-in-parent-class visibility. Behavior here diverges from both Eloquent and symfony/serializer, and divergence discovered late is expensive.

Sequencing.

  1. Benchmark spike (2–3 days). Compare against bounded-closure hydration, Model::hydrate(), and our existing serializer on realistic object counts. If the delta is under ~20% on our workloads, stop — the archived-risk premium is not worth it.
  2. Port + adapter + matrix tests. No direct dependency in application code.
  3. Build-time pre-generation as a deploy step, emitted alongside config:cache in CI, baked into the container image.
  4. Pilot one hot path only (a high-volume read model or export job), instrumented with timing before/after.
  5. Decide: fork internally, or retire the port at the next PHP upgrade.

Operational Impact

Maintenance. We become the maintainer on day one. The codebase is small, so periodic patches for PHP-version churn are feasible — but budget a fork pinned to an internal VCS repository or private Packagist entry, plus a named owner. An unowned archived dependency in a hot path is a latent outage.

Support. No upstream support, no issue triage, no CVE feed, no security advisories. We must add it to the internal dependency-risk register and treat any future vulnerability as unfixed-by-default.

Scaling. Hydration throughput scales well once hydrators are warm. The scaling hazard is horizontal: on cold start with N containers, each generates the same files independently — a thundering herd on the cache directory, and potential write contention on shared storage. Eliminate this with deploy-time pre-generation baked into the image, not lazy runtime generation. Hydrator instances are cached per class, so steady-state memory is negligible. OPcache should be configured with validate_timestamps=0 in production for the generated directory, which in turn mandates a cache clear on every deploy.

Failure modes to design against.

  • Unwritable target directory → runtime exception precisely under load, after the code path looked healthy in dev.
  • Stale generated classes across blue/green overlap → two app versions sharing one target directory can serve hydrators built against the wrong class shape. Version the directory per release.
  • Uninitialized typed property → fatal error when an input array key is absent; the hydrator has no schema knowledge, so this must be guarded in the adapter.
  • Readonly or enum properties → potential fatal at generation time; caught only by the compatibility matrix.
  • Silent validation bypass → the most dangerous mode because it produces no error at all; a malformed payload reaches a domain object fully populated.

Ramp-up. Low technical ramp-up for a mid-level PHP developer — an afternoon with the README. The real ramp-up cost is organizational: because this is a performance optimization with no user-visible feature, a future team will look at it, see an archived package, and remove it without understanding why it exists. Ship it with an ADR containing the benchmark numbers, the port boundary, and an explicit retirement trigger (next PHP major upgrade). Without that artifact, the adoption will not survive contact with the next maintainer.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource