hdaklue/laravel-dto-morph-cast
A Laravel package that casts Eloquent model attributes into DTO classes, morphing between raw database values and typed data transfer objects for cleaner, safer model attributes.
Scope of this update: v1.1.2 is a patch release on the 1.1.x line. The published release note contains only a GitHub compare link and no described changes, fixes, or CVE references. There is no prior assessment on file, so this is a baseline evaluation of the package at v1.1.2, not a delta review. The absence of change detail is itself a data point about release hygiene and should be resolved before adoption.
Architecture fit: laravel-dto-morph-cast targets a narrow, real gap: Eloquent's native polymorphic relations (morphTo/morphMany) return hydrated models or raw arrays, forcing domain code to work with untyped structures. This package provides a custom cast that maps the morph type plus attributes into a typed DTO. It fits applications where a DTO boundary already exists (API resources, command/query handlers, event payloads) and where polymorphic parents are a known modeling pattern — notifications, comments, audit records, attachments. It does not fit applications that intentionally keep Eloquent models as the domain layer, or that have standardized on a broader DTO framework (e.g. spatie/laravel-data); in those cases this introduces a second, competing serialization convention.
Integration feasibility: Mechanically low-friction. Adoption is a Composer require plus a $casts entry on the relevant attributes and a DTO implementing whatever contract the package defines. No database migration, no service provider wiring beyond package discovery, no queue or infra change. Expect a one-to-three-day spike to validate the contract shape against an existing DTO.
Technical risk: Moderate, concentrated in project maturity rather than code complexity. The package is single-maintainer (hdaklue) with low adoption signal, and the v1.1.x release notes are undocumented. Casts sit on the hydration hot path and at the serialization boundary, so a defect surfaces as corrupted payloads or runtime exceptions rather than a degraded page. The specific unknowns are the supported Laravel/PHP matrix, whether DTO construction is contract-based or convention-based, and how the cast behaves when a morph type resolves to a class that no longer exists.
Key questions:
composer.json constraints for PHP and illuminate/*, and is Laravel 11/12 explicitly supported?toArray()/toJson(), API resources, and queue serialization?Stack fit: Assumes Laravel with Eloquent, PHP 8.x, Composer, and standard package auto-discovery. Compatible with Laravel's morphMap if the package resolves types through the morph map rather than raw class names — this must be verified, since bypassing the morph map is a common failure in packages of this type. Verify coexistence with any existing Attribute casts (AsArrayObject, AsEnumCollection) on the same model; casts do not compose, and the last registration wins.
Migration path: Purely additive and reversible. Add the cast attribute-by-attribute on one model, remove any equivalent accessor/mutator in the same commit to avoid double transformation, then expand. Rollback is a one-line revert with no data migration, which keeps the blast radius small. Do not attempt a codebase-wide conversion in a single PR.
Compatibility: Pin to ^1.1 and let the lockfile hold the exact patch. Confirm the package's Laravel constraint covers the app's current major and the next planned upgrade before adopting, otherwise the cast becomes a blocker on the framework upgrade. Because 1.1.2 shipped with no changelog, read the diff between 1.1.1 and 1.1.2 before bumping in an existing integration.
Sequencing:
composer audit and a dependency-review check to CI so an unannounced future release cannot land silently.Maintenance: Bus factor of one. Expect infrequent releases, and note that 1.1.2 shipped without a human-readable changelog, which suggests release automation without curation. Budget for the possibility of upstreaming a fix or forking; the package surface is small enough that a fork is a realistic fallback rather than a rewrite. Assign an internal owner even though the code is trivial.
Support: Community-only via GitHub issues; no vendor, no SLA, no commercial backing. Internal triage must own any production incident. Escalation path is "read the source," which is viable here given the small codebase.
Scaling: Negligible infrastructure impact — the cast runs per-attribute during hydration, adding microseconds per model. The real scaling concern is architectural: if the cast performs lazy class resolution or triggers additional queries, it can mask N+1 patterns by making relation access look cheap. Load-test the endpoint that uses it before broad rollout, and confirm eager loading still behaves as expected.
Failure modes:
toArray()/queue payloads in an unexpected shape, breaking downstream consumers or already-queued jobs after a deploy.Ramp-up: Low. An engineer familiar with Eloquent casts can be productive in under a day; the DTO convention is the only real learning curve. Cost is in establishing and documenting the convention, not in the package itself. Recommend a short internal note with two worked examples (one morphTo, one morphMany) to prevent divergent usage across teams.
Recommendation: Conditionally adopt for a bounded, well-tested surface. Gate full adoption on obtaining the v1.1.2 diff, confirming the supported Laravel/PHP matrix, and verifying unknown-morph-type behavior — all three are cheap to check and each independently determines whether the package is safe at a serialization boundary.
How can I help you explore Laravel packages today?