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

Hydrator Laravel Package

patchlevel/hydrator

Hydrate objects to arrays and back without calling constructors. Supports final and readonly classes, nested structures, enums, dates, lazy hydration, field renaming, and metadata caching with a developer-friendly, fully typed API.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit patchlevel/hydrator is a framework-agnostic PHP serialization/hydration library, not a Laravel package. There is no service provider, config file, facade, or Eloquent integration — it operates purely on plain PHP objects. For a Laravel codebase this means it occupies the same architectural slot as spatie/laravel-data, Symfony Serializer, or hand-rolled fromArray()/toArray() methods on DTOs. Its distinguishing capabilities are narrow but real:

  • Constructor bypass hydration makes final, readonly, and promoted-property DTOs viable without factory boilerplate, which fits well with the modern Laravel style of immutable value objects at the boundaries (Form Requests → DTO → Action → Resource).
  • Attribute-driven field mapping (rename/exclude) gives you a stable external contract decoupled from internal property names — the main reason teams reach for a serializer instead of json_encode.
  • Pluggable guessers/extensions is the right extensibility model; it lets us add project-specific normalizers (money objects, strongly-typed IDs, VO collections) without forking.
  • Serialization groups (new in 2.1.0) closes the biggest functional gap versus Symfony Serializer: one DTO can now emit different payload shapes per context (internal queue vs. public API vs. admin export) without duplicate classes or exclude attributes piling up. This is directly relevant to our boundary-DTO architecture.
  • Skippable middleware (new in 2.1.0), combined with the existing middleware pipeline, gives a single interception point around hydration/extraction — the natural home for invariant assertions, decode-failure logging, and audit trails. Previously we would have had to build this into our own wrapper.
  • Middleware generation (docs/enhancement in 2.1.0) reduces the boilerplate cost of writing those middleware, which matters because middleware is now a first-class part of our containment story.
  • Crypto-shredding is the strategically interesting feature: per-subject key destruction as an erasure mechanism. That is a compliance-shaped feature, not a convenience one, and it implies the library is doing field-level encryption with key custody that we own.

Critically, it does not do validation, rule inference, Eloquent model hydration, query-builder integration, or resource transformation. spatie/laravel-data bundles all of those. Adopting hydrator means accepting a narrower tool and keeping validation in Form Requests — which is a legitimate architecture, just a deliberate one. Groups do not change this: groups select which fields appear, not whether values are valid.

Integration feasibility Low effort, high reversibility. composer require patchlevel/hydrator, bind a configured Hydrator instance as a singleton in a small service provider, inject it into actions/controllers. No migration, no schema change, no framework coupling. A pilot can be stood up in under a day. The only hard prerequisite is PHP ≥ 8.1 for the core (8.4 if we want lazy proxies), which we need to confirm against our runtime matrix. 2.1.0 adds no new runtime prerequisite.

Technical risk The dominant risk remains adoption and bus factor, not code quality:

  • Star count and dependents remain effectively unproven (our dataset for this review did not refresh the counts — re-check before sign-off). We would still be among the first production users, which means we find the edge cases and we own the workarounds.
  • The project is small-team (Patchlevel — credible PHP maintainers, but a boutique). 2.1.0 shipped with three contributors including one outside the core pair, which is a modest positive signal for resilience but not a structural change.
  • 2.1.0 is a clean minor release: no breaking changes, no deprecations, no removals. 4 PRs, 0 issues closed, one of which is a mutation-testing hardening fix (StackHydratorTest timeout counter). That is a quiet, disciplined release — it partially offsets the "expect churn before 3.x" concern without eliminating it. The 2.x line now looks more stable than the 2.0.x-era release cadence implied.
  • The Stryker mutation-testing badge is a genuine positive signal for internal correctness — better than most packages at this star count, and 2.1.0 continues to invest in it.
  • Constructor bypass is a double-edged capability. Skipping __construct also skips invariant enforcement. Any object whose constructor validates (e.g., assert($amount >= 0)) becomes hydratable into an invalid state from untrusted array input. 2.1.0 gives us the tool to mitigate this centrally (assertion middleware) rather than per-DTO, but the design-level risk remains and must be handled by policy: hydrate only from trusted, typed sources, never directly from raw request payloads without validation upstream.
  • New surface area in 2.1.0 carries its own risk. Groups and middleware are both implicit-by-attribute mechanisms: a class with a typo'd or missing group attribute silently emits a wrong-shaped payload, and a class that skips a middleware silently bypasses whatever that middleware enforces. Skip semantics must be deny-listed for security-relevant middleware (invariant checks, redaction) so a future DTO cannot opt out of them by accident. This is a review-rule item, not a library defect.
  • Crypto-shredding is an audit item, not a checkbox. Encryption, key derivation, key storage, rotation, and deletion semantics all become our responsibility. If we market erasure guarantees to customers based on this feature, we need legal and security review before, not after.
  • Small-package DX externality: low training-data presence means AI coding assistants and new hires will guess the API incorrectly — and 2.1.0 makes this worse before it gets better, because models will confidently produce 2.0-era code without groups or middleware. Ramp-up cost per developer is low, but support-ticket cost per incident is higher.

Key questions

  1. What problem are we actually solving — serialization only, or DTO + validation + Eloquent integration? If the latter, spatie/laravel-data is the lower-risk answer and this evaluation should end here.
  2. Do we have a bounded, non-critical context (queue job payloads, cache DTOs, webhook deserialization) to pilot in for one sprint before committing?
  3. What is our tolerance for a single-maintainer dependency in a code path that touches persisted payloads?
  4. Do we need the crypto-shredding capability, and if so, who owns the key management and the GDPR erasure claim?
  5. Are we on PHP 8.4, and do we want lazy proxies in the first iteration or defer?
  6. What is the exit cost — can we swap to Symfony Serializer or laravel-data without rewriting business logic? (Answer: yes, if we keep the Hydrator behind our own thin Serializer interface.)
  7. (new) Does the groups feature let us retire part of our own abstraction — e.g. replace per-context mapper classes with one grouped DTO — or does it just add a second way to express payload variants? We should answer this inside the pilot, not before it.
  8. (new) Which middleware are non-skippable by policy (invariant assertions, redaction, audit logging), and where is that enforced in review/CI?

Verdict: Technically sound, strategically still unproven but improving. 2.1.0 is a low-risk, additive release that materially strengthens the case (groups, middleware) without altering the core risk profile (bus factor, constructor-bypass invariants, crypto-shredding). Approve for a scoped pilot behind an internal abstraction; do not standardize org-wide, and do not adopt with crypto-shredding enabled in v1. Widen the pin from 2.0.x to ^2.1.

Integration Approach

Stack fit Good fit for a Laravel app that has already committed to immutable DTOs at HTTP/queue boundaries. Poor fit for a team that leans on spatie/laravel-data for validation-plus-hydration, or on Eloquent $casts/toArray() for model serialization. The library is additive: it replaces hand-written fromArray()/toArray() pairs on ~10–50 DTOs, not the whole persistence layer. Groups make it a better fit than before for teams that currently maintain multiple near-duplicate DTO classes purely to vary payload shape by context.

Recommended containment pattern:

App\Support\Serialization\Serializer (interface: toArray(object, ?array $groups), fromArray(class, array))
   └── HydratorSerializer (wraps patchlevel/hydrator)

This one interface is the whole risk-mitigation strategy. It makes the dependency swappable, gives us one place to add logging on hydration failures, and prevents Patchlevel\Hydrator\* types from leaking into domain code. Update: keep the Serializer interface even though groups and middleware now cover much of what it did — it is the exit hatch, not a duplication. Do not let the interface grow into a re-implementation of the library's attribute system.

Middleware registration should live entirely inside HydratorSerializer's construction (or a dedicated SerializationServiceProvider), so the middleware list is reviewable in one diffable place rather than scattered across DTO attributes.

Migration path Incremental and opt-in, by design:

  1. Spike (2–3 days, +half a day for 2.1.0 features): bind the hydrator, hydrate 3 representative DTOs — one with enums, one with a nested VO collection, one readonly final with renamed fields. Then add one group across two contexts and one assertion middleware, and confirm the skip attribute behaves as expected. Confirm behavior on our PHP version.
  2. Pilot surface: queue job payloads or cache values, not HTTP request input. These are trusted-producer, versioned-payload scenarios where constructor bypass and schema drift are contained — and where groups are genuinely useful (internal consumer needs the full object; the outbound webhook needs a trimmed view).
  3. Widen to API response DTOs once patterns are established and the group vocabulary is settled.
  4. Explicitly do not replace Form Request validation — validation stays upstream, hydration happens after validated(). Groups are not a validation mechanism and must not be treated as one.

Migration off an existing solution (e.g., laravel-data) is a rewrite of attribute annotations and any magic-property access, and a feature regression (no validation, no rule inference, no model integration). Do not migrate existing working DTOs to hydrator for its own sake; apply it only to new code and to DTOs that are currently hand-rolled. Groups reduce the future case for laravel-data's partial/contextual serialization; they do not retroactively justify a migration.

Compatibility

  • PHP version gate is the first check — 8.1 minimum for core, 8.4 for lazy proxies. Confirm against the app's and CI's matrix.
  • 2.1.0 is backward compatible with 2.0.x. Bumping within the pilot is a composer update with no code change required; groups and middleware are opt-in. This is exactly the kind of release we wanted to see after pinning.
  • Revise the pinning policy: ^2.1 with lockfile, treat minor bumps as reviewable-not-automatic, majors as planned work. The 2.0 → 2.1 delta supports loosening from the original patch-only pin.
  • No conflict with spatie/laravel-data, Symfony Serializer, or Laravel's container; they can coexist. Ensure we do not end up with two serialization strategies on the same DTO, which produces confusing "which attribute wins" bugs.
  • Payload compatibility is the real concern: attribute-based rename/exclude plus group membership means the serialized array shape is coupled to property names, attributes, and which groups the caller passed. Renaming a PHP property is a breaking change to any persisted payload; moving a property between groups is an equally breaking change to any consumer that relied on the old shape. Treat payloads as a public contract and version them ({"_v": 1, ...}) for anything durable — queues, caches, event stores.

Sequencing

  1. Spike + team review of the containment interface, extended to cover ?array $groups (week 1)
  2. PHP version / CI confirmation, security review scoped to crypto-shredding (weeks 1–2, parallel)
  3. Adopt 2.1.0 within the spike; evaluate groups against a real two-context DTO before standardizing a group vocabulary (week 1–2)
  4. Pilot in queue/cache path with payload versioning and a non-skippable assertion middleware (weeks 2–4)
  5. Retrospective: measure DX win vs. actual DTO count touched, and whether groups removed or added cognitive load; decide on broader rollout
  6. Only then evaluate crypto-shredding as a separate, security-led initiative

Operational Impact

Maintenance Ongoing maintenance is minimal — small API surface, no configuration, no service provider to keep in sync with Laravel majors. 2.1.0 did not change this. The cost that does accrue is dependency governance: a low-adoption, small-team package needs an owner on our side, a pinning policy (lockfile-pinned ^2.1, minors reviewable), and an upgrade checklist per release. Budget roughly a day per major version bump; minors on the evidence of 2.1.0 should be well under an hour.

Two hidden maintenance items now:

  • Serialized payload schema ownership. Once DTO shapes are persisted in queues or caches, every property rename is a data migration. Without discipline this becomes the leading source of production incidents attributable to the library.
  • Group and middleware vocabulary ownership (new). Unmanaged, groups proliferate (admin, admin_v2, internal, webhook) and middleware stacks accumulate per-DTO exceptions until nobody can predict a payload shape from reading the class. Assign ownership: a single SerializationGroups enum-like constant set and a central middleware registry, reviewed like a public API.

Support

  • Upstream support is best-effort GitHub issues from a boutique maintainer. No SLA, no commercial support tier, no large community. 2.1.0's three-contributor release is encouraging but does not constitute a support commitment.
  • Internal support cost: near-zero for routine use, elevated for novel failures because there is no Stack Overflow corpus and AI assistants will hallucinate the API — now specifically by emitting pre-2.1 code. Mitigate with a short internal runbook, 2–3 canonical examples in the repo, and a note that groups/middleware exist.
  • Recommend a named internal owner (one engineer) and a documented "if upstream goes quiet, here's the fork/swap plan." The containment interface makes this credible.

Scaling

  • Hydration is CPU-bound and O(payload size); the library benchmarks favorably against reflection-heavy serializers, which matters for high-throughput queue consumers deserializing thousands of payloads per minute. Worth a micro-benchmark against our actual DTO shapes during the spike rather than trusting README claims. Middleware is now on the hot path — each registered middleware adds per-hydration overhead, so keep the global stack short and measure before adding a fifth or sixth.
  • Memory: deeply nested structures hydrate as full object graphs. Lazy proxies (PHP 8.4) are the intended mitigation for large aggregate graphs — attractive, but they are a new-ish PHP feature and introduce proxy-identity subtleties (instanceof, ===, serialization of proxies). Defer to a second phase. Note that groups are the cheaper lever for reducing payload size before we reach for proxies.
  • Horizontal scaling is unaffected: stateless, no shared state, no I/O.

Failure modes Ranked by likelihood × impact:

Failure Likelihood Impact Mitigation
Invalid object constructed via bypass (invariants skipped) Medium High Hydrate only post-validation, from trusted producers; enforce invariants via non-skippable assertion middleware (now viable in 2.1.0) rather than per-DTO code
Payload schema drift after property rename or group reassignment → failed/partial hydration High over time High Version all persisted payloads; treat array shape and group membership as a contract; contract tests per DTO per context; decode-failure alerting
DTO silently skips a security-relevant middleware Low–Medium High Deny-list skippable middleware; add a CI/architecture test asserting critical middleware applies to all serialized DTOs
Group misconfiguration → field leaked to a public payload or missing from a consumer Medium High Explicit per-context contract tests (assert exact key set, not just "hydrates without error"); review group changes as API changes
Uninitialized/missing property silently defaulted or throwing mid-deserialization Medium Medium Explicit contract tests per DTO; fail-fast on unknown keys in pilot
Breaking change in a 2.x → 3.x bump Medium Medium Lockfile pin to ^2.1; read changelog; containment interface limits blast radius
Upstream abandonment Low (near term) High Containment interface; ability to fork or swap to Symfony Serializer in ~1 sprint
Crypto-shredding misuse — key loss = irreversible data loss; wrong key scope = failed erasure claim Low (if unused) Critical Do not enable in v1; security + legal review; KMS-backed key custody; documented destruction audit trail
Two serialization strategies coexisting → inconsistent API output Medium Medium One DTO = one strategy; lint/review rule

Ramp-up Fast for a competent Laravel engineer — the API is small (hydrate/extract, a handful of attributes, Normalizer registration), docs are current and published, and behavior is intuitive to anyone who has used a serializer. Expect half a day to productivity, one to two days to fluency with attributes, nested normalizers, and guesser registration. No framework-specific knowledge required. 2.1.0 adds groups and middleware, both familiar concepts to anyone who has used Symfony Serializer or a Laravel middleware stack — budget one additional half-day for the team to agree on group semantics and the middleware registry.

Compensating cost: because the package is obscure, onboarding material must be internal. Write a one-page "how we use hydrator here" doc with 3 examples, the containment-interface rule, the group vocabulary, and the non-skippable middleware policy — otherwise new hires and AI tooling will produce subtly wrong code (most likely 2.0-era code without groups), and review becomes the enforcement mechanism.

TPM recommendation: Fund a one-sprint, one-engineer pilot in a queue/cache path behind a Serializer interface, with payload versioning, the 2.1.0 features explicitly in scope (one grouped DTO across two contexts, one non-skippable assertion middleware), and crypto-shredding disabled. Gate broader adoption on the pilot showing a measurable reduction in DTO boilerplate with zero hydration failures and a group vocabulary a reviewer can predict from the class definition. Revisit the make-vs-buy decision against spatie/laravel-data at that checkpoint — for most Laravel teams the incumbent still wins on adoption and validation bundling, but 2.1.0 narrows the gap materially: constructor bypass on readonly final DTOs, pluggable normalizers, and now group-based contextual serialization plus a middleware interception point is a genuinely better-shaped tool for a team with a disciplined boundary-DTO architecture.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib