### Configure AutoMapper Bundle Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/configuration.md Customize bundle behavior by defining options in `config/packages/automapper.yaml`. This example shows various settings like class prefix, constructor strategy, date time format, and mapping paths. ```yaml automapper: class_prefix: "Symfony_Mapper_" constructor_strategy: 'auto' date_time_format: !php/const DateTimeInterface::RFC3339 check_attributes: true auto_register: true map_private_properties: true allow_readonly_target_to_populate: false remove_default_properties: true normalizer: enabled: false only_registered_mapping: false priority: 1000 loader: eval: false cache_dir: "%kernel.cache_dir%/automapper" reload_strategy: "always" serializer_attributes: true api_platform: false object_mapper: false name_converter: null mapping: paths: - "%kernel.project_dir%/src/Entity" mappers: - source: AutoMapper\Bundle\Tests\Fixtures\User target: AutoMapper\Bundle\Tests\Fixtures\UserDTO reverse: false ``` -------------------------------- ### Install AutoMapper using Composer Source: https://github.com/jolicode/automapper/blob/main/README.md Use this command to add AutoMapper to your PHP project via Composer. ```shell composer require jolicode/automapper ``` -------------------------------- ### Create AutoMapper with Custom Configuration Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/configuration.md Instantiate `AutoMapper` with a custom `Configuration` object to control mapper generation and behavior. This example sets several options including class prefix, constructor strategy, date format, and caching. ```php use AutoMapper\Configuration; use AutoMapper\AutoMapper; $configuration = new Configuration( classPrefix: 'Mapper_', constructorStrategy: 'auto', dateTimeFormat: \DateTimeInterface::RFC3339, attributesChecking: true, autoRegister: true, mapPrivateProperties: true, allowReadonlyTargetToPopulate: false, strictTypes: false, reloadStrategy: \AutoMapper\Loader\FileReloadStrategy::ON_CHANGE, allowExtraProperties: false, extractTypesFromGetter: false, ); $autoMapper = AutoMapper::create(configuration: $configuration); ``` -------------------------------- ### Define Address Class Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/identifier.md Example User and Address classes to illustrate nested objects. ```php class User { public string $name; /** @var Address[] */ public array $address; } class Address { public string $id; public string $street; public string $city; } ``` -------------------------------- ### Configure Constructor Strategy with `#[Mapper]` Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/mapper-attribute.md Use the `#[Mapper]` attribute to specify a constructor strategy for a class. This example sets the constructor strategy to `NEVER` for the `Entity` class. ```php #[Mapper(constructorStrategy: ConstructorStrategy::NEVER)] class Entity { public string $foo; } ``` -------------------------------- ### Convert custom normalizer logic using transformers Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/migrate.md Example of using the `#[MapTo]` attribute with a `transformer` to replicate custom normalizer logic, such as adding a `virtualProperty`. ```php #[MapTo(target: 'array', property: 'virtualProperty', transformer: MyTransformer::class)] class App\Entity\MyEntity { // ... } ``` -------------------------------- ### PHP Mapping Configuration Source: https://github.com/jolicode/automapper/blob/main/tests/AutoMapperTest/README.md Defines a mapping for a `BuiltinClass` using AutoMapper. This example demonstrates mapping a `DateInterval` object to an array representation. ```php map(new BuiltinClass(new \DateInterval('P1Y')), 'array'); ``` -------------------------------- ### Define Mapper with Source and Target Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/cache-warmup.md Use the `#[Mapper]` attribute on a class to define a mapping. Specify the `source` and `target` arguments to control which transformations are generated during cache warmup. This example generates a mapper from `array` to `Entity` and vice versa. ```php #[Mapper(source: 'array', target: 'array')] class Entity { public string $foo; } ``` -------------------------------- ### Define Mapper with Multiple Targets Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/cache-warmup.md When using the `#[Mapper]` attribute, you can specify an array of targets to generate multiple mappers simultaneously. This example generates mappers from `array` to `array` and `array` to `EntityDto`. ```php #[Mapper(source: 'array', target: ['array', EntityDto::class])] class Entity { public string $foo; } ``` -------------------------------- ### Register a class for migration Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/migrate.md Register a class in the `mappings` configuration to start migrating its normalization process. This ensures the default automapper behavior is tested against `symfony/serializer` for this class. ```yaml automapper: normalizer: enabled: true only_registered_mapping: true mappings: mappers: - { source: App\Entity\MyEntity, target: 'array' } ``` -------------------------------- ### Accessing Type Information in Custom Transformers Source: https://github.com/jolicode/automapper/blob/main/docs/upgrading/upgrading-10.0.md Demonstrates how to access type information from `SourcePropertyMetadata` and `TargetPropertyMetadata` objects in custom transformers after upgrading to AutoMapper 10.0. This example checks if the source type is nullable. ```php class MyTransformer implements PropertyTransformerSupportInterface { public function supports(SourcePropertyMetadata $source, TargetPropertyMetadata $target, MapperMetadata $mapperMetadata): bool { if ($source->type->isNullable()) { return false; } // ... } } ``` -------------------------------- ### MapFrom with Priority and Ignore Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/attributes.md Demonstrates using `#[MapFrom]` with a specified `priority` and `ignore` flag. The `ignore` flag defaults to `false` when not specified. ```php class EntityDto { #[MapFrom(source: Entity::class, ignore: false, priority: 10)] public string $title; } ``` -------------------------------- ### Instantiate AutoMapper Source: https://context7.com/jolicode/automapper/llms.txt Factory method to bootstrap an AutoMapper instance with optional configuration, cache directory, name converter, custom transformers, providers, and Doctrine object manager. ```APIDOC ## AutoMapper::create() Factory method that bootstraps an `AutoMapper` instance with optional configuration, cache directory, name converter, custom transformers, providers, and Doctrine object manager. Returns an `AutoMapperInterface`. ### Method Factory method ### Parameters #### Configuration - **configuration** (`Configuration` object) - Optional - Configuration object for AutoMapper. - **cacheDirectory** (`string`) - Optional - Directory for caching generated mappers. Omit to use in-memory eval loader. ### Example ```php use AutoMapper\AutoMapper; use AutoMapper\Configuration; use AutoMapper\ConstructorStrategy; use AutoMapper\Loader\FileReloadStrategy; $configuration = new Configuration( classPrefix: 'Mapper_', constructorStrategy: ConstructorStrategy::AUTO, // AUTO | ALWAYS | NEVER dateTimeFormat: \DateTimeInterface::RFC3339, attributeChecking: true, // enable allowed_attributes / ignored_attributes at runtime autoRegister: true, // generate mappers on the fly mapPrivateProperties: true, // map private/protected properties allowReadOnlyTargetToPopulate: false, strictTypes: false, // add declare(strict_types=1) to generated files reloadStrategy: FileReloadStrategy::ON_CHANGE, // NEVER | ON_CHANGE | ALWAYS allowExtraProperties: false, // map extra props when target implements ArrayAccess extractTypesFromGetter: false, // use getter return type for property type extraction ); $autoMapper = AutoMapper::create( configuration: $configuration, cacheDirectory: '/var/cache/automapper', // omit to use in-memory eval loader ); ``` ``` -------------------------------- ### Pre-generate Mappers for Production Source: https://context7.com/jolicode/automapper/llms.txt Use `cache:warmup` to pre-generate mapper classes, avoiding runtime code generation and disk writes in production. Inspect mappings with `debug:mapper`. ```bash # Generate mapper PHP classes into the cache directory php bin/console cache:warmup # Inspect the mapping for a specific pair php bin/console debug:mapper "App\Entity\User" "App\DTO\UserDTO" ``` -------------------------------- ### Configure mapping to a target property with #[MapFrom] Source: https://context7.com/jolicode/automapper/llms.txt Use #[MapFrom] on a target property to specify how it should be populated from a source. It mirrors #[MapTo] functionality, allowing source property renaming, transformers, identifiers, and type overrides for incoming values. Source-specific configurations are supported. ```php use AutoMapper\Attribute\MapFrom; class ArticleDTO { // Read from source property named 'title' instead of 'name' #[MapFrom(property: 'title')] public string $name; // Source-specific: different source field for Article vs array #[MapFrom(source: Article::class, property: 'title')] #[MapFrom(source: 'array', property: 'name')] public string $displayName; // Apply transformer on the incoming value #[MapFrom(transformer: 'strtoupper')] public string $category; // Mark property as identifier for collection merging #[MapFrom(identifier: true)] public string $id; // Override inferred type #[MapFrom(targetPropertyType: 'string')] public mixed $legacyField; // Override serializer #[Ignore] for a specific source #[MapFrom(source: Article::class, ignore: false)] public string $overrideIgnored; } ``` -------------------------------- ### Use AutoMapperInterface in a Controller Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/installation.md Inject and use the `AutoMapperInterface` service within your Symfony controllers to map objects. This example demonstrates mapping a source object to an array. ```php use AutoMapper\AutoMapperInterface; class MyController { public function __construct(private AutoMapperInterface $autoMapper) { } #[Route('/my-route', name: 'my_route')] public function index() { $source = new Source(); $target = $this->autoMapper->map($source, 'array'); return new JsonResponse($target); } } ``` -------------------------------- ### Basic AutoMapper Usage Source: https://github.com/jolicode/automapper/blob/main/README.md Instantiate AutoMapper and map data to a target class. Ensure the target class is defined. ```php $mapper = AutoMapper::create(); $target = $mapper->map($data, Target::class); ``` -------------------------------- ### Call Service Methods with service() Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/expression-language.md Use the `service()` function in `#[MapTo]` attributes to invoke methods on registered services. You can reference services by their alias or fully qualified class name. ```php class Entity { #[MapTo(transformer: "service('my_service').transform(source)")] public string $name; // Or without an alias #[MapTo(transformer: "service('App\\Service\\MyService').transform(source)")] public string $name; #[MapTo(if: "service('my_service').check()")] public int $age; } ``` -------------------------------- ### Map Provider with Attribute Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/provider.md Use the `#[MapProvider]` attribute on the target class to specify which provider should be used for its instantiation. ```php use AutoMapper\Attribute\MapProvider; #[MapProvider(provider: MyProvider::class)] class Entity { } ``` -------------------------------- ### MapFrom with Multiple Sources Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/attributes.md Configure `#[MapFrom]` to handle mapping from multiple sources (a class and an array) to the same property, using an array for the `source` argument. ```php class EntityDto { #[MapFrom(source: Entity::class, property: 'title')] #[MapFrom(source: 'array', property: 'name')] public string $name; #[MapFrom(source: [Entity::class, 'array'], property: 'bar')] public string $foo; } ``` -------------------------------- ### Basic Object Mapping with AutoMapper Source: https://github.com/jolicode/automapper/blob/main/docs/index.md Instantiate AutoMapper and use the map method to convert a source object to a target object. The library generates and caches mapping logic. ```php use AutoMapper\AutoMapper; $automapper = AutoMapper::create(); $source = new Source(); $target = $automapper->map($source, Target::class); ``` -------------------------------- ### Implement Custom Provider Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/provider.md Create a custom provider by implementing the `ProviderInterface`. This allows you to define custom logic for instantiating target objects. ```php use AutoMapper\Provider\ProviderInterface; class MyProvider implements ProviderInterface { public function provide(string $targetType, mixed $source, array $context): object|null { return new $targetType(); } } ``` -------------------------------- ### Custom Object Instantiation with #[MapProvider] Source: https://context7.com/jolicode/automapper/llms.txt Use #[MapProvider] to specify a custom class for object instantiation, useful for fetching data from a database or other sources. The provider must implement ProviderInterface. Set to 'false' to disable default providers. ```php use AutoMapper\Attribute\MapProvider; use AutoMapper\AutoMapper; use AutoMapper\Provider\EarlyReturn; use AutoMapper\Provider\ProviderInterface; class UserRepository implements ProviderInterface { public function __construct(private \PDO $db) {} public function provide(string $targetType, mixed $source, array $context): object|null { if ($targetType !== User::class || !isset($source['id'])) { return null; // fall back to constructor } $stmt = $this->db->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([$source['id']]); $row = $stmt->fetch(); if (!$row) { // EarlyReturn: skip property mapping and return null directly return new EarlyReturn(null); } $user = new User($row['first_name'], $row['last_name'], new \DateTimeImmutable($row['created_at'])); return $user; // AutoMapper will overwrite properties from source } } // Register on the class #[MapProvider(provider: UserRepository::class)] class User { /* ... */ } // Disable automatic Doctrine/API Platform provider for this class #[MapProvider(provider: false)] class ImmutableEntity { /* ... */ } // Standalone usage $autoMapper = AutoMapper::create(providers: [new UserRepository($pdo)]); $user = $autoMapper->map(['id' => 42, 'first_name' => 'Jane'], User::class); ``` -------------------------------- ### Configure AutoMapper Bundle with YAML Source: https://context7.com/jolicode/automapper/llms.txt Configure AutoMapper settings in `config/packages/automapper.yaml` to customize its behavior, such as class prefix, date time format, and mapping paths. ```yaml automapper: class_prefix: "App_Mapper_" constructor_strategy: 'auto' # auto | always | never date_time_format: !php/const DateTimeInterface::RFC3339 check_attributes: true auto_register: true map_private_properties: true allow_readonly_target_to_populate: false remove_default_properties: true # recommended: true for new projects serializer_attributes: true # respect #[Groups], #[Ignore], #[MaxDepth] api_platform: false # enable API Platform IRI provider object_mapper: false # implement Symfony ObjectMapperInterface doctrine: false # enable Doctrine entity fetching provider normalizer: enabled: false only_registered_mapping: false priority: 1000 loader: eval: false cache_dir: "%kernel.cache_dir%/automapper" reload_strategy: "always" # always in dev, never in prod mapping: paths: - "%kernel.project_dir%/src/Entity" # auto-register classes with #[Mapper] mappers: - source: App\Entity\User target: App\DTO\UserDTO reverse: true # also register UserDTO → User - source: App\Entity\User target: array ``` -------------------------------- ### Instantiate AutoMapper Standalone Source: https://context7.com/jolicode/automapper/llms.txt Create an `AutoMapper` instance using the `AutoMapper::create()` factory method. Configure options like cache directory, name converter, and custom transformers. Omit the cache directory to use an in-memory eval loader. ```php use AutoMapper\AutoMapper; use AutoMapper\Configuration; use AutoMapper\ConstructorStrategy; use AutoMapper\Loader\FileReloadStrategy; $configuration = new Configuration( classPrefix: 'Mapper_', constructorStrategy: ConstructorStrategy::AUTO, // AUTO | ALWAYS | NEVER dateTimeFormat: \DateTimeInterface::RFC3339, attributeChecking: true, // enable allowed_attributes / ignored_attributes at runtime autoRegister: true, // generate mappers on the fly mapPrivateProperties: true, // map private/protected properties allowReadOnlyTargetToPopulate: false, strictTypes: false, // add declare(strict_types=1) to generated files reloadStrategy: FileReloadStrategy::ON_CHANGE, // NEVER | ON_CHANGE | ALWAYS allowExtraProperties: false, // map extra props when target implements ArrayAccess extractTypesFromGetter: false, // use getter return type for property type extraction ); $autoMapper = AutoMapper::create( configuration: $configuration, cacheDirectory: '/var/cache/automapper', // omit to use in-memory eval loader ); ``` -------------------------------- ### Binding Accessor Parameters to Context with #[MapToContext] Source: https://context7.com/jolicode/automapper/llms.txt Use #[MapToContext] on constructor or method parameters to read values from the mapping context. This enables accessor methods that accept arguments, such as currency or locale. ```php use AutoMapper\Attribute\MapToContext; use AutoMapper\AutoMapper; class PriceCalculator { public function __construct(private float $basePrice) {} public function getFormattedPrice( #[MapToContext('currency')] string $currency, #[MapToContext('locale')] string $locale = 'en_US', ): string { return number_format($this->basePrice, 2, '.', ',') . ' ' . $currency; } } class PriceDTO { public string $formattedPrice; } $autoMapper = AutoMapper::create(); $calc = new PriceCalculator(99.95); $dto = $autoMapper->map($calc, PriceDTO::class, [ 'map_to_accessor_parameter' => [ 'currency' => 'EUR', 'locale' => 'de_DE', ], ]); // $dto->formattedPrice === '99.95 EUR' ``` -------------------------------- ### Early Return from Provider Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/provider.md Return an `EarlyReturn` object from the `provide` method to bypass property mapping and return the instantiated object directly. ```php use AutoMapper\Provider\EarlyReturn; use AutoMapper\Provider\ProviderInterface; class MyProvider implements ProviderInterface { public function provide(string $targetType, mixed $source, array $context): object|null { return new EarlyReturn(new $targetType()); } } ``` -------------------------------- ### PHP Iterator Mapping Configuration Source: https://github.com/jolicode/automapper/blob/main/tests/AutoMapperTest/README.md Provides multiple test cases for mapping using an iterator. Each yielded item represents a distinct mapping scenario, allowing for varied inputs and expected outputs. ```php 'foo', 'int' => ['foo' => 1]]; yield 'ok' => $autoMapper->map($user, UserConstructorDTOWithRelation::class); $user = ['name' => 'foo', 'int' => ['foo' => 2]]; yield 'ko' => $autoMapper->map($user, UserConstructorDTOWithRelation::class); })(); ``` -------------------------------- ### Custom Transformer Before 10.0 Source: https://github.com/jolicode/automapper/blob/main/docs/upgrading/upgrading-10.0.md Illustrates the signature of a custom transformer implementing `PropertyTransformerSupportInterface` before version 10.0. ```php class MyTransformer implements PropertyTransformerSupportInterface { public function supports(TypesMatching $types, SourcePropertyMetadata $source, TargetPropertyMetadata $target, MapperMetadata $mapperMetadata): bool { // ... } } ``` -------------------------------- ### Map Data to Existing Object Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/identifier.md Fetch an existing object and map incoming data to it. This is useful when updating records. ```php // We fetch existing object from database $user = $this->entityManager->find(User::class, $id); // We map data to existing object $mapper->map($requestValue, $user); ``` -------------------------------- ### Configure mapping from a source property with #[MapTo] Source: https://context7.com/jolicode/automapper/llms.txt Use #[MapTo] on a source property to control how it maps to a target. Supports renaming, transformers via expression language or callbacks, conditional mapping, groups, and date/depth overrides. Can be repeated for different targets. ```php use AutoMapper\Attribute\MapTo; class Article { // Rename: map $title → target property 'name' #[MapTo(property: 'name')] public string $title; // Target-specific rename: 'name' for ArticleDTO, 'title' for array #[MapTo(target: ArticleDTO::class, property: 'name')] #[MapTo(target: 'array', property: 'title')] public string $slug; // Ignore for one target, include for another #[MapTo(target: ArticleDTO::class, ignore: true)] #[MapTo(target: 'array', ignore: false)] public string $internalNote; // Expression language transformer #[MapTo(transformer: "source.status === 'draft' ? 'pending' : 'active'")] public string $status; // Static callback transformer: receives ($value, $source, $context) #[MapTo(transformer: [self::class, 'slugify'])] public string $rawTitle; // Conditional mapping via expression language #[MapTo(if: 'source.isPublished and (context["show_meta"] ?? false)')] public string $metaDescription; // Groups #[MapTo(groups: ['admin', 'internal'])] public string $secretField; // DateTime format override #[MapTo(dateTimeFormat: \DateTimeInterface::ATOM)] public \DateTimeImmutable $publishedAt; // Max depth for nested objects #[MapTo(maxDepth: 2)] public array $comments; public static function slugify(string $value, self $source, array $context): string { return strtolower(str_replace(' ', '-', $value)); } } ``` -------------------------------- ### Basic Mapping with Context Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/context.md Pass a context array as the third argument to the map method to alter mapping behavior. ```php $source = new User(); $target = $autoMapper->map($source, UserDTO::class, ['key' => 'value']); ``` -------------------------------- ### Register AutoMapperBundle in config/bundles.php Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/installation.md Register the main bundle class in your `config/bundles.php` file to enable the bundle's functionality. ```php return [ // ... AutoMapper\Symfony\Bundle\AutoMapperBundle::class => ['all' => true], ]; ``` -------------------------------- ### Mapping Context Options for Runtime Behavior Source: https://context7.com/jolicode/automapper/llms.txt The mapping context array passed to map() or mapCollection() allows runtime control over mapping behavior. Options include groups, attribute whitelisting/blacklisting, null/uninitialized value handling, datetime formatting, and circular reference management. ```php use AutoMapper\AutoMapper; use AutoMapper\MapperContext; $autoMapper = AutoMapper::create(); $source = new User('Jane', 'Doe', new \DateTimeImmutable('2024-01-15')); // ── Groups: map only properties annotated with matching group ────────────── $dto = $autoMapper->map($source, UserDTO::class, ['groups' => ['public']]); // ── Allowed attributes (whitelist) ──────────────────────────────────────── $dto = $autoMapper->map($source, UserDTO::class, [ 'allowed_attributes' => ['firstName', 'address' => ['city']], ]); // ── Ignored attributes (blacklist) ──────────────────────────────────────── $dto = $autoMapper->map($source, UserDTO::class, [ 'ignored_attributes' => ['internalNote'], ]); // ── Skip null values (keep target value when source property is null) ────── $target = new UserDTO(); $target->firstName = 'Alice'; $result = $autoMapper->map( new User('', '', new \DateTimeImmutable()), $target, ['skip_null_values' => true] ); // ── Skip uninitialized values ────────────────────────────────────────────── $result = $autoMapper->map($source, $target, ['skip_uninitialized_values' => true]); // ── DateTime format override ─────────────────────────────────────────────── $dto = $autoMapper->map($source, 'array', [ MapperContext::DATETIME_FORMAT => 'Y-m-d', ]); // ── Circular reference handling ──────────────────────────────────────────── $node = new TreeNode('root'); $node->parent = $node; $mapped = $autoMapper->map($node, TreeNodeDTO::class, [ 'circular_reference_handler' => fn($src, $ctx) => null, // or 'circular_reference_limit' => 0 to throw CircularReferenceException ]); // ── Provide missing constructor arguments ────────────────────────────────── $dto = $autoMapper->map($source, UserDTO::class, [ 'constructor_arguments' => [ UserDTO::class => ['createdAt' => new \DateTime('2024-01-01')], ], ]); ``` -------------------------------- ### Conditional Mapping with Dynamic Callback Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/conditional-mapping.md Use a dynamic callback (an instance method) to define mapping conditions. The method can access the object's properties and should return a boolean. ```php class Source { public bool $propertyIsValid = true; #[MapTo(if: 'isPropertyValid')] public $property; public function isPropertyValid(): bool { return $this->propertyIsValid; } } ``` -------------------------------- ### Map Object to New Object Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/source-and-target.md Use this when mapping from a source object to a new target object of a specified class. ```php $source = new User(); $target = $autoMapper->map($source, UserDTO::class); ``` -------------------------------- ### Use Static Callback as Transformer Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/transformer.md Employ a static method as a transformer. The callback receives the value, the source object, and the context array. ```php class Source { #[MapTo(transformer: [self::class, 'transform'])] public string $property; public static function transform(string $value, Source $source, array $context): string { return strtoupper($value); } } ``` -------------------------------- ### Implement Property Transformer Support Interface Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/transformer.md Implement PropertyTransformerSupportInterface to automatically apply a custom transformer based on source and target property metadata. This avoids manual specification in attributes. ```php namespace App\Transformer; use AutoMapper\Metadata\MapperMetadata; use AutoMapper\Metadata\SourcePropertyMetadata; use AutoMapper\Metadata\TargetPropertyMetadata; use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerSupportInterface; class UrlTransformer implements PropertyTransformerSupportInterface { public function __construct(private UrlGeneratorInterface $urlGenerator) { } public function supports(SourcePropertyMetadata $source, TargetPropertyMetadata $target, MapperMetadata $mapperMetadata): bool { return $source->type->isIdentifiedBy(TypeIdentifier::INT) && $source->property === 'id' && $target->property === 'url'; } public function transform(mixed $value, object|array $source, array $context): mixed { return $this->urlGenerator->generate('my_route', ['id' => $value]); } } ``` -------------------------------- ### Handle Missing Constructor Arguments Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/context.md Use `constructor_arguments` to provide values for constructor parameters that are not available in the source object. This ensures objects can be instantiated even with incomplete source data. ```php class UserDto { public function __construct(private string $name, private \DateTime $createdAt) {} } $source = new User(); $source->name = 'Jane'; $target = $autoMapper->map($source, UserDTO::class, [ 'constructor_arguments' => [ UserDTO::class => ['createdAt' => new \DateTime('2021-01-01')] ] ]); ``` -------------------------------- ### Mapping with Groups Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/context.md Use the 'groups' option in the context to map only properties flagged with specific group names on both source and target objects. ```php $source = new User(); $target = $autoMapper->map($source, UserDTO::class, ['groups' => ['read']]); ``` -------------------------------- ### Basic Collection Mapping Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/map-collection.md Use mapCollection() to transform a collection of source objects into a collection of target objects. Ensure AutoMapper is created and source objects are instantiated. ```php use AutoMapper\AutoMapper; $automapper = AutoMapper::create(); $sources = [ new Source('value1'), new Source('value2'), new Source('value3'), ]; $targets = $automapper->mapCollection($sources, Target::class); ``` -------------------------------- ### Conditional Mapping with Static Callback Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/conditional-mapping.md Define mapping conditions using a static callback method. This method should accept the source object and context array and return a boolean. ```php class Source { public bool $propertyIsValid = true; #[MapTo(if: [self::class, 'isPropertyValid'])] public $property; public static function isPropertyValid(Source $source, array $context): bool { return $source->propertyIsValid && ($context['custom_key'] ?? false) === true; } } ``` -------------------------------- ### Map to Accessor Parameter with Context Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/context.md Use `map_to_accessor_parameter` to specify values for accessor method parameters. Link parameters to context using `#[MapToContext]`. ```php class User { public function __construct(private string $name) {} public function getName(#[MapToContext('suffix')] string $suffix): string { return $this->name . $suffix; } } $source = new User(name: 'Jane'); $target = $autoMapper->map($source, UserDTO::class, [ 'map_to_accessor_parameter' => ['suffix' => ' Doe'] ]); ``` -------------------------------- ### Define Mapping Groups with #[MapTo] Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/groups.md Use the `groups` argument in `#[MapTo]` to map a property only when the context includes at least one of the specified groups. ```php class Source { #[MapTo(target: 'array', groups: ['group1', 'group2'])] public $groupedProperty; } ``` -------------------------------- ### Implement Custom Property Transformers Source: https://context7.com/jolicode/automapper/llms.txt Use `PropertyTransformerInterface` for service-based transformers or `PropertyTransformerSupportInterface` for auto-applied transformers. Ensure necessary imports and dependencies are available. ```php use AutoMapper\Attribute\MapTo; use AutoMapper\AutoMapper; use AutoMapper\Metadata\MapperMetadata; use AutoMapper\Metadata\SourcePropertyMetadata; use AutoMapper\Metadata\TargetPropertyMetadata; use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerInterface; use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerSupportInterface; use Symfony\Component\TypeInfo\TypeIdentifier; // ── Manually referenced transformer ─────────────────────────────────────── class UrlTransformer implements PropertyTransformerInterface { public function __construct(private \Symfony\Component\Routing\RouterInterface $router) {} public function transform(mixed $value, object|array $source, array $context): mixed { return $this->router->generate('user_show', ['id' => $value]); } } class UserResource { #[MapTo(property: 'profileUrl', transformer: UrlTransformer::class)] public int $id; } // ── Auto-applied transformer (no attribute needed on properties) ─────────── class MoneyTransformer implements PropertyTransformerSupportInterface { public function supports( SourcePropertyMetadata $source, TargetPropertyMetadata $target, MapperMetadata $mapperMetadata, ): bool { // Auto-apply when source type is Money and target is string return $source->type?->isIdentifiedBy(TypeIdentifier::OBJECT) && is_a($source->type->getClassName(), \Money\Money::class, true) && $target->type?->isIdentifiedBy(TypeIdentifier::STRING); } public function transform(mixed $value, object|array $source, array $context): mixed { /** @var \Money\Money $value */ return $value->getAmount() . ' ' . $value->getCurrency()->getCode(); } } $autoMapper = AutoMapper::create( propertyTransformers: [ new UrlTransformer($router), new MoneyTransformer(), ], ); $dto = $autoMapper->map($userResource, UserDTO::class); // $dto->profileUrl === '/users/42' ``` -------------------------------- ### Implement Custom Property Transformer Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/transformer.md Create a custom transformer by implementing PropertyTransformerInterface. This is useful for complex transformations or when external dependencies are needed. ```php namespace App\Transformer; use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerInterface; class UrlTransformer implements PropertyTransformerInterface { public function __construct(private UrlGeneratorInterface $urlGenerator) { } public function transform(mixed $value, object|array $source, array $context): mixed { return $this->urlGenerator->generate('my_route', ['id' => $value]); } } ``` -------------------------------- ### Register a reverse mapping for denormalization migration Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/migrate.md Use the `reverse: true` option when registering a mapping to migrate the denormalizer for the specified class. ```yaml automapper: normalizer: enabled: true only_registered_mapping: true mappings: mappers: - { source: App\Entity\MyEntity, target: 'array', reverse: true } ``` -------------------------------- ### MapFrom with Specific Source and Property Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/attributes.md Specify the source class (`Entity::class`) and the property name (`'title'`) for the `#[MapFrom]` attribute. ```php class EntityDto { #[MapFrom(source: Entity::class, property: 'title')] #[MapFrom(source: 'array', property: 'name')] public string $name; } ``` -------------------------------- ### Map to Array with Target Type Hint Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/type.md When mapping to an array, specify `targetPropertyType` to enforce a specific type conversion for the mapped property. ```php class Entity { #[MapTo(target: 'array', targetPropertyType: 'int')] public string $number; } ``` -------------------------------- ### Configure `#[Mapper]` with Priority Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/mapper-attribute.md Define multiple `#[Mapper]` attributes with different priorities. The attribute with the higher priority (e.g., `2`) will be used for the specified mapping, overriding lower-priority attributes (e.g., `1`). ```php #[Mapper(source: EntityDto::class, constructorStrategy: ConstructorStrategy::NEVER, priority: 2)] class Entity { public string $foo; } #[Mapper(constructorStrategy: ConstructorStrategy::ALWAYS, priority: 1)] class EntityDto { public string $foo; } ``` -------------------------------- ### Map Object to Existing Object Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/source-and-target.md Use this to update an existing target object with values from a source object. The target object is modified in place. ```php $source = new User(); $target = new UserDTO(); $autoMapper->map($source, $target); ``` -------------------------------- ### Map Nested Properties using Dot Notation Source: https://context7.com/jolicode/automapper/llms.txt Use dot notation in the `property` parameter of `#[MapTo]` or `#[MapFrom]` to map between flat DTOs and nested object graphs. This simplifies mapping complex object structures. ```php use AutoMapper\Attribute\MapTo; use AutoMapper\AutoMapper; class UserDTO { #[MapTo(property: 'address.street')] public string $streetAddress; #[MapTo(property: 'address.city')] public string $cityAddress; public string $name; } class Address { public string $street; public string $city; } class User { public Address $address; public string $name; public function __construct() { $this->address = new Address(); } } $autoMapper = AutoMapper::create(); $dto = new UserDTO(); $dto->streetAddress = '123 Main St'; $dto->cityAddress = 'Springfield'; $dto->name = 'John Doe'; /** @var User $user */ $user = $autoMapper->map($dto, User::class); // $user->address->street === '123 Main St' // $user->address->city === 'Springfield' // $user->name === 'John Doe' ``` -------------------------------- ### Define DTO and Domain Classes for Nested Mapping Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/nested.md Define DTO and domain classes with nested properties. Use #[MapTo] with dot notation to specify the nested property path for mapping. ```php class UserDto { #[MapTo(property: 'address.street')] public string $streetAddress; #[MapTo(property: 'address.city')] public string $cityAddress; public string $name; } class User { public Address $address; public string $name; public function __construct() { $this->address = new Address(); } } class Address { public string $street; public string $city; } ``` -------------------------------- ### Declare Mappings for Cache Warmup Source: https://context7.com/jolicode/automapper/llms.txt Explicitly declare mappings in `config/packages/automapper.yaml` when `auto_register` is set to `false` for production environments. ```yaml # config/packages/automapper.yaml — declare mappings to warm up automapper: auto_register: false # require explicit declaration in production mapping: mappers: - source: App\Entity\Product target: App\DTO\ProductDTO reverse: true - source: App\Entity\Product target: array ``` -------------------------------- ### Configure Mappers in YAML Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/cache-warmup.md Specify the mappings to be generated during cache warmup by listing source and target classes in the `automapper.mapping.mappers` configuration. This ensures mappers are ready before the first request. ```yaml automapper: mapping: mappers: - source: App\Entity\User target: App\Api\DTO\User - source: App\Entity\User target: array reverse: true ``` -------------------------------- ### Set DateTime Format on Property Attribute Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/date-time.md Specify a DateTime format directly on a `#[MapTo]` or `#[MapFrom]` attribute. This format takes precedence over mapper attributes and bundle configurations. ```php class Source { #[MapTo(dateTimeFormat: \DateTimeInterface::ATOM)] public \DateTimeImmutable $dateTime; } ``` -------------------------------- ### Class-level mapper configuration with #[Mapper] Source: https://context7.com/jolicode/automapper/llms.txt Apply #[Mapper] to a class to override global AutoMapper configuration. Supports constructor strategy, datetime format, strict types, and discriminator mappings for inheritance. Can be repeated with different priorities for specific source/target combinations. ```php use AutoMapper\Attribute\Mapper; use AutoMapper\ConstructorStrategy; use AutoMapper\Metadata\Discriminator; // Never use constructor for any mapping targeting Entity #[Mapper(constructorStrategy: ConstructorStrategy::NEVER)] class Entity { public string $id; public string $name; } // Apply only when source is EntityDTO, with highest priority #[Mapper(source: EntityDTO::class, constructorStrategy: ConstructorStrategy::ALWAYS, priority: 10)] class EntityReadModel { public function __construct(public readonly string $id, public readonly string $name) {} } // Inheritance / discriminator: map abstract Pet → concrete DogDTO or CatDTO #[Mapper(discriminator: new Discriminator( mapping: [ DogDTO::class => Dog::class, CatDTO::class => Cat::class, ] ))] abstract class PetDTO { public string $name; } // Discriminator when target is array (use a 'type' property) #[Mapper(target: 'array', discriminator: new Discriminator( property: 'type', mapping: ['dog' => Dog::class, 'cat' => Cat::class] ))] abstract class Pet { public string $name; } ``` -------------------------------- ### Mapping with Allowed Attributes Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/context.md Specify 'allowed_attributes' in the context to map only a subset of properties. This check is performed on the source object's property names. ```php $source = new User(); $target = $autoMapper->map($source, UserDTO::class, ['allowed_attributes' => ['id']] ); ``` -------------------------------- ### Clone Object Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/source-and-target.md Use this for a deep clone of a source object to a new object of the same class. Sub-objects will also be cloned, not referenced. ```php $source = new User(); $target = $autoMapper->map($source, User::class); assert($source !== $target); ``` -------------------------------- ### Map a collection Source: https://context7.com/jolicode/automapper/llms.txt Maps an iterable of source items to an array of target instances in one call, applying the same context to every element. ```APIDOC ## AutoMapperInterface::mapCollection() Maps an iterable of source items to an array of target instances in one call, applying the same context to every element. ### Method `mapCollection(iterable $sources, string $targetClass, ?array $context = null): array` ### Parameters #### Sources - **sources** (`iterable`) - An iterable of source items to map. #### Target Class - **targetClass** (`string`) - The target class name for each item in the collection. #### Context - **context** (`?array`) - Optional array of context to be applied to each element mapping. ### Examples ```php use AutoMapper\AutoMapper; $autoMapper = AutoMapper::create(); $users = [ new User('Alice', 'Smith', new \DateTimeImmutable()), new User('Bob', 'Jones', new \DateTimeImmutable()), ]; /** @var UserDTO[] $dtos */ $dtos = $autoMapper->mapCollection($users, UserDTO::class); // Returns array // With context applied to every element $dtos = $autoMapper->mapCollection($users, UserDTO::class, [ 'groups' => ['public'], ]); ``` ``` -------------------------------- ### MapFrom Attribute on Method Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/attributes.md Use `#[MapFrom]` on a method of the target object to map a property named 'title' from the source to this method. ```php class EntityDto { private string $name; #[MapFrom(property: 'title')] public function setName($name): void { $this->name = $name; } } ``` -------------------------------- ### Register Service for Expression Language Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/expression-language.md Register a service with the `#[AsAutoMapperExpressionService]` attribute to make it accessible within AutoMapper's expression language. You can provide an alias for easier referencing. ```php namespace App\Service; use AutoMapper\Symfony\Attribute\AsAutoMapperExpressionService; #[AsAutoMapperExpressionService(alias: 'my_service')] class MyService { public function transform(Entity $entity): string { return 'transformed'; } public function check(): bool { return false; } } ``` -------------------------------- ### Mapping Collections with AutoMapper Source: https://github.com/jolicode/automapper/blob/main/docs/index.md Use the mapCollection method to map an array of source objects to an array of target objects. ```php $sources = [$source1, $source2, $source3]; $targets = $automapper->mapCollection($sources, Target::class); ``` -------------------------------- ### Collection Mapping with Context Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/map-collection.md Customize individual object mappings within a collection by passing a context array to mapCollection(). This context is applied to each mapping operation. ```php $context = ['groups' => ['read']]; $targets = $automapper->mapCollection($sources, Target::class, $context); ``` -------------------------------- ### MapTo Attribute on Class for Virtual Property Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/attributes.md Use `#[MapTo]` on a class to define a virtual property named 'virtualProperty'. ```php #[MapTo(property: 'virtualProperty')] class Entity {} ``` -------------------------------- ### Prioritize Transformers with `PrioritizedPropertyTransformerInterface` Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/transformer.md Implement `PrioritizedPropertyTransformerInterface` to define a priority for transformers. The transformer with the highest integer value returned by `getPriority` will be used when multiple transformers can handle the same property. ```php namespace App\Transformer; use AutoMapper\Transformer\PropertyTransformerSupportInterface; use AutoMapper\Transformer\PrioritizedPropertyTransformerInterface; class UrlTransformer implements PropertyTransformerSupportInterface, PrioritizedPropertyTransformerInterface { // ... public function getPriority(): int { return 10; } } ``` -------------------------------- ### Debug a Specific Mapper with `debug:mapper` Command Source: https://github.com/jolicode/automapper/blob/main/docs/bundle/debugging.md Use the `debug:mapper` command to inspect the mapping details of a specific mapper. This is helpful for understanding how objects are mapped and identifying unmapped properties. ```bash php bin/console debug:mapper User UserDTO ``` -------------------------------- ### Set DateTime Format on Mapper Attribute Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/date-time.md Define a DateTime format using the `#[Mapper]` attribute. This setting is overridden by property attributes but takes precedence over bundle configurations. ```php #[Mapper(dateTimeFormat: \DateTimeInterface::ATOM)] class Source { public \DateTimeImmutable $dateTime; } ``` -------------------------------- ### MapTo with Specific Target and Property Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/attributes.md Specify the target class (`EntityDto::class`) and the property name (`'name'`) for the `#[MapTo]` attribute. ```php class Entity { #[MapTo(target: EntityDto::class, property: 'name')] #[MapTo(target: 'array', property: 'title')] public string $title; } ``` -------------------------------- ### Register Custom Provider Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/provider.md Register your custom provider when creating the `AutoMapper` instance. This ensures AutoMapper uses your provider for instantiation. ```php use AutoMapper\AutoMapper; $autoMapper = AutoMapper::create(providers: [new MyProvider()]); ``` -------------------------------- ### Conditional Mapping with PHP Function Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/conditional-mapping.md Use a PHP function to determine if a property should be mapped. The function must return a boolean value and can only accept the source object and context array as arguments. ```php class Source { #[MapTo(if: 'boolval')] public string $property = ''; } ``` -------------------------------- ### Class Inheritance Mapping with Discriminator Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/inheritance.md Use Discriminator with a mapping of target classes to source classes when AutoMapper needs to determine the correct class to instantiate based on the instance of the property. ```php #[Mapper(discriminator: new Discriminator( mapping: [ DogDto::class => Dog::class, CatDto::class => Cat::class, ] ))] abstract class Pet { /** @var string */ public $name; /** @var PetOwner */ public $owner; } ``` -------------------------------- ### Skipping Null Values during Mapping Source: https://github.com/jolicode/automapper/blob/main/docs/getting-started/context.md Enable 'skip_null_values' in the context to prevent mapping null values from the source object, preserving existing values in the target object. ```php $source = new User(); $source->name = null; $target = new UserDTO(); $target->name = 'Jane'; $target = $autoMapper->map($source, $target, ['skip_null_values' => true]); assert($target->name === 'Jane'); ``` -------------------------------- ### Define Property Groups with #[Groups] Source: https://github.com/jolicode/automapper/blob/main/docs/mapping/serializer.md Use the `#[Groups]` attribute to specify which property groups a property belongs to. This controls which properties are mapped based on the serialization context groups. ```php use Symfony\Component\Serializer\Attribute\Groups; class Source { #[Groups(['group1', 'group2'])] public $groupedProperty; } ```