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

Automapper Laravel Package

jolicode/automapper

A fast, flexible object-to-object mapper for PHP inspired by .NET's AutoMapper. Map between objects, arrays, and scalars using attributes, with automatic type conversion, nested mappings, custom transformers, and zero-config defaults. Framework-agnostic, works great with Symfony.

Deep Wiki
Context7

Getting Started

Install with Composer and confirm the PHP version target (the package leans on modern PHP features and AST codegen):

composer require jolicode/automapper

Build a mapper once and reuse it (it is a service, not a per-call helper):

use AutoMapper\AutoMapper;

$mapper = AutoMapper::create();

$dto    = $mapper->map($entity, UserDto::class);   // object -> object (populates class)
$array  = $mapper->map($entity, 'array');          // object -> array
$entity = $mapper->map($payload, UserEntity::class); // array -> object

Where to look first:

  1. AutoMapper::create() / AutoMapperBuilder — the supported entry points for wiring configuration, cache, and constructor behavior.
  2. AutoMapper\Attribute\Mapper, MapFrom, MapTo — the attribute surface you will use daily for name/shape mismatches.
  3. AutoMapper\Transformer\* — when built-in coercions aren't enough (dates, enums, value objects, collections).
  4. The Symfony bundle (jolicode/automapper-bundle) if you're in a Laravel/Symfony-style DI app — it registers AutoMapperInterface and a debug command.

First useful case: mapping an Eloquent-ish entity or domain model into an API DTO, and the reverse for write payloads. Start with one DTO, one attribute override, and grow from there.

Implementation Patterns

DTO / response shaping. Map entities to typed DTOs at the controller or resource boundary so serialization and validation both operate on a stable class. Keep DTOs plain (public promoted properties or getters/setters) — the mapper infers types via property-info.

Reverse mapping for writes. map($request->validated(), CreateUser::class) gives you a command/entity object without hand-written hydration. Use MapFrom/MapTo when input keys differ from property names.

Attribute-driven config is the default dialect. Put behavior next to the class rather than in a central bootstrap:

use AutoMapper\Attribute\MapFrom;

class UserDto
{
    public string $id;
    #[MapFrom(source: User::class, property: 'display_name')]
    public string $displayName;
    #[MapFrom(source: User::class, property: 'created_at')]
    public \DateTimeImmutable $createdAt;
}

Register pair-level config with #[Mapper(source: X::class, target: Y::class)] on the target when you need to override the whole mapping.

Custom transformers for value objects (Money, Email, UUID). Implement the transformer interface, declare supports() narrowly (source/target property types), and register it on the builder or via the bundle's service tag. Keep transformers pure and side-effect free — they run inside generated code and may run many times.

Collections and nesting. Register a per-item transformer (or a MapTo/MapFrom) for array<Foo> / Collection<Bar>; the mapper will not guess the element type from an untyped array. Nested object properties are mapped recursively, so deep graphs work — but see circular references below.

Context passing. Use the mapper context argument for per-call switches (e.g., "with relations", output format) and read it in transformers, rather than creating separate mapper instances per variant.

Framework integration. In a DI app, bind a single AutoMapperInterface and inject it. Prefer the bundle/extension so cache and transformer registration are centralized instead of calling create() in a helper.

Gotchas and Tips

  • Codegen is warm-up cost, not steady-state cost. The first map() for a pair compiles a PHP class; subsequent calls are fast. Ensure your cache backend (PSR-16) is persistent in production and warm it during deploy — don't let the first user request pay for it.
  • Cache invalidation is manual. Changing a DTO, attribute, or transformer does not automatically regenerate cached mappers in every setup. Clear the cache directory / version the namespace on deploy.
  • Circular references blow up. Bidirectional entity graphs (User → Posts → User) will recurse until memory fails. Provide a circular-reference handler or map to a shallower DTO; the mapper has no way to know where to cut.
  • Constructor vs. property hydration matters. With constructor-based hydration, every required parameter must be resolvable from the source, or you get a compile/runtime error. Use AutoMapperBuilder options to control constructor use and private-property reading; don't toggle them ad hoc per call.
  • Type coercions are not magic. String → DateTimeImmutable, int → backed enum, string → value object all need transformers or a matching source type. Silent nulls on required typed properties produce TypeErrors at map time — good for finding holes, bad for debugging.
  • Untyped arrays lose element types. array $tags maps as array, but array<Comment> needs explicit configuration. Same for Laravel Collection vs. plain array.
  • Debug via the generated code. When a mapping is surprising, dump the compiled mapper class (or use the bundle's automapper:debug-style command) — you're reading exactly what executes. This is faster than reasoning about attributes.
  • Extension points to prefer: custom transformers for values, MapFrom/MapTo for naming, Mapper attribute for pair-level rules, context for runtime variation. Avoid subclassing the AutoMapper class itself; you'll lose compatibility with builder/bundle wiring.
  • Keep mapping out of hot loops if you can. Though compiled mappers are fast, repeated AutoMapper::create() calls (a common Laravel service-provider mistake) rebuild and recompile. Bind it as a singleton.
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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons