- What does league/object-mapper actually do?
- league/object-mapper is a reflection-based hydrator that turns structured data such as request arrays, decoded JSON, or queue payloads into typed PHP objects like DTOs, command objects, and value objects. It resolves constructor arguments, nested objects, and collections, and uses PHP attributes to declare property mappings and casts. It is deliberately not an ORM, a validator, or a format-aware serializer, so its sweet spot is a single anti-corruption boundary between transport shapes and your domain types.
- How do I install league/object-mapper in a Laravel app?
- Install it with composer require league/object-mapper. There is no service provider, facade, or config file to publish, because the package is framework-agnostic PSR-4 code with no Laravel dependency. In Laravel you bind it into the container yourself, ideally wrapping it behind a small internal interface so the vendor namespace never leaks into your application layer.
- Which PHP and Laravel versions does league/object-mapper support?
- The package declares its PHP constraints in composer.json and tests them in CI on the GitHub repository, so check those two places before committing. There is no Laravel-specific release track since the package does not depend on the framework, so Laravel support is really just a question of your PHP version. For a target of PHP 8.3 or 8.4, verify behavior with a spike rather than assuming from the README.
- How is league/object-mapper different from spatie/laravel-data or Symfony Serializer?
- Spatie's laravel-data is Laravel-native and bundles validation rules, resource transformation, and request integration, while Symfony Serializer is a full serializer with format awareness. league/object-mapper is intentionally smaller: it constructs strict typed objects from arrays with an extensible cast layer and nothing else. Pick it when you want a dependency-light mapper and are willing to own the Laravel glue; pick spatie/laravel-data when you want those conveniences included.
- How do I map nested objects and arrays of DTOs?
- You declare the target type on the property or constructor parameter, add attributes describing the mapping, and let the mapper recurse into the nested structure. Arrays of child DTOs are resolved through the cast layer rather than hand-written loops, so one parent DTO can describe an entire payload tree. Verify circular references and deeply nested collections in a spike, since those are common reflection edge cases.
- Can it handle enums, dates, and custom value objects like Money or UserId?
- Enums, date/time values, and scalar coercion are handled by the cast layer, which is designed to be extended. You can register your own casters so domain value objects such as Money, UserId, or Email hydrate without forking the package. Confirm each cast you rely on against the actual source and a test case, because the README does not document every edge case.
- How does it integrate with Laravel FormRequest validation?
- Keep validation and construction separate: validate in a FormRequest, pass the validated array to the mapper, and get back a typed command or query DTO. Mapping failures surface as mapping exceptions rather than ValidationException, so without a translation layer malformed client input becomes a 500 instead of a 422. Write that translation once in your adapter and the rest of the application stays clean.
- Is league/object-mapper safe to use in production?
- Treat it as a pilot rather than a standard. It is a single-maintainer League package with roughly 36 stars, zero dependents, and almost no production adoption footprint to inherit, and League packages have been archived before, so assume you may need to fork it. Contain it behind a small internal interface of five methods or fewer so the vendor remains a swappable implementation detail.
- Does it support readonly properties, promoted constructor parameters, and union or intersection types?
- Reflection-based mappers are acutely sensitive to PHP type-system changes, and this is exactly where support matrices tend to be optimistic. Readonly properties, promoted constructor params, default values, nullable-versus-missing-key semantics, enum backing types, union, intersection, and DNF types all need to be verified by spike, not assumed. Also check the failure semantics for unknown extra keys and partial coercion, and whether a strict mode exists.
- What alternatives should I evaluate before adopting it?
- The closest alternatives are cuyz/valinor, spatie/laravel-data, and Symfony Serializer's object-constructor path. Valinor and Symfony Serializer offer strict hydration with different ergonomics and error models, while spatie/laravel-data adds Laravel-native validation and resource handling. If your team's mental model is Eloquent models plus API Resources, a mapper adds little and becomes a second, competing hydration mechanism.