mark-gerarts/automapper-plus-bundle
Symfony bundle integrating AutoMapperPlus for fast, configurable object-to-object mapping. Provides service wiring, profiles, and easy mapping between DTOs, entities, and view models with type safety and custom transformations.
A Symfony bundle for AutoMapper+. To see it in action, check out the demo app.
The bundle is available on packagist:
$ composer require mark-gerarts/automapper-plus-bundle
This bundle supports Symfony 3.4 through 8.x.
Don't forget to register the bundle:
$bundles = [
new AutoMapperPlus\AutoMapperPlusBundle\AutoMapperPlusBundle(),
// ...
];
The automapper is available as a service: automapper_plus.mapper (or just type hint
the AutoMapperPlus\AutoMapperInterface).
You can register mapping configurations by creating a class that implements the
AutoMapperConfiguratorInterface. This configurator class will have to define a
configure method, that gets passed the configuration object:
<?php
namespace Demo;
use AutoMapperPlus\AutoMapperPlusBundle\AutoMapperConfiguratorInterface;
use AutoMapperPlus\Configuration\AutoMapperConfigInterface;
use Demo\Model\Employee\Employee;
use Demo\Model\Employee\EmployeeDto;
class AutoMapperConfig implements AutoMapperConfiguratorInterface
{
public function configure(AutoMapperConfigInterface $config): void
{
$config->registerMapping(Employee::class, EmployeeDto::class)
->forMember('fullName', function (Employee $source) {
return $source->getFirstName() . ' ' . $source->getLastName();
});
// And so on..
}
}
If your configurator class is registered as a service and service autoconfiguration is enabled, the bundle will tag it automatically.
For example, with a typical Symfony services.yaml:
services:
_defaults:
autowire: true
autoconfigure: true
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
and a configurator class like:
<?php
namespace App\Mapper;
use AutoMapperPlus\AutoMapperPlusBundle\AutoMapperConfiguratorInterface;
use AutoMapperPlus\Configuration\AutoMapperConfigInterface;
class AutoMapperConfig implements AutoMapperConfiguratorInterface
{
public function configure(AutoMapperConfigInterface $config): void
{
// Register mappings...
}
}
the bundle will pick it up automatically.
If your configurator is not covered by service discovery, you can register it manually as a service. If autoconfiguration is enabled for that service, no manual tag is needed:
services:
App\Mapper\AutoMapperConfig:
autowire: true
autoconfigure: true
If autoconfiguration is disabled, register the class as a service and tag it
with automapper_plus.configurator. You can optionally add a priority parameter
to the tag.
services:
App\Mapper\AutoMapperConfig:
tags:
- { name: automapper_plus.configurator }
You can register all your mappings in a single configurator class, or spread it across multiple classes. The choice is yours!
The options for the mapper can be configured. Create a config/packages/automapper_plus.yaml
file (or add to your config.yaml for older Symfony versions) with the following contents:
auto_mapper_plus:
options:
create_unregistered_mappings: true
These options correspond with the ones of the Options object.
Full reference (Not all options are supported at the moment, more coming soon!):
auto_mapper_plus:
options:
# These options are example values, and not necessarily the default
# ones. If an option is not provided, the base library's default will
# be used.
create_unregistered_mappings: true
skip_constructor: true
use_substitution: true
ignore_null_properties: false
# Note that this should be the service name, and not necessarily the
# FQCN.
property_accessor: AutoMapperPlus\AutoMapperPlusBundle\PropertyAccessor\SymfonyPropertyAccessorBridge
Using the configuration is completely optional, you can just set the options directly
on the Options object in one of your configurators using $config->getOptions().
The bundle contains a bridge for the Symfony PropertyAccessor. It provides 2 variants:
SymfonyPropertyAccessorBridge is basically only the functionality of
Symfony's component, meaning you can NOT set private properties directly
(which is a good thing if you want to be more strict).DecoratedPropertyAccessor uses the Symfony property access, but falls
back to the default in case of failure. This means private properties will
be handled, even if they don't have a getter/setter.Both options provide allow to use fromProperty with full property paths,
e.g. forMember('aProperty', Operation::fromProperty('some.nested[child]'));.
Note that other usages of property paths have not been tested and are not
guaranteed to work. It will be investigated in the 2.x release
(related issue).
Sample service definition:
services:
AutoMapperPlus\AutoMapperPlusBundle\PropertyAccessor\SymfonyPropertyAccessorBridge:
arguments:
$propertyAccessor: '@property_accessor'
In your automapper_plus.yaml configuration:
auto_mapper_plus:
options:
property_accessor: 'AutoMapperPlus\AutoMapperPlusBundle\PropertyAccessor\SymfonyPropertyAccessorBridge'
For more info regarding the automapper itself, check out the project page.
How can I help you explore Laravel packages today?