Manual Mapping using a Class Factory Method
This mapping method is deprecated.
This mapping method is deprecated as it is not considered a good practice.
You should instead use AsObjectMapper
explained in Manual Mapping using an
Object Mapper chapter. You will be able to map third-party
classes, separate the logic from the model, and inject other services into the
mapper.
This is one way to have a custom logic of mapping an object to another object.
You can make your DTO implement the MapToObjectInterface
or
MapFromObjectInterface
and create the required mapper methods.
Suppose you are using the brick/money
library to represent money in your
application, and you need to map the Money
object to the following DTO:
namespace App\Dto;
class MoneyDto
{
public function __construct(
private string $amount,
private string $currency,
) {
}
public function getAmount(): string
{
return $this->amount;
}
public function getCurrency(): string
{
return $this->currency;
}
}
Mapping from another Object
You can have your DTO implement the MapFromObjectInterface
and create the
mapFromObject()
method:
namespace App\Dto;
use Brick\Money\Money;
use Rekalogika\Mapper\Context\Context;
use Rekalogika\Mapper\MethodMapper\MapFromObjectInterface;
use Rekalogika\Mapper\MethodMapper\SubMapperInterface;
final class MoneyDto implements MapFromObjectInterface
{
// ...
public static function mapFromObject(
object $source,
SubMapperInterface $mapper,
Context $context
): static {
if (!$source instanceof Money) {
throw new \InvalidArgumentException('Source must be instance of ' . Money::class);
}
return new static(
$source->getAmount()->__toString(),
$source->getCurrency()->getCurrencyCode(),
);
}
}
Then, the next time you are mapping from the Money
object to the MoneyDto
object, the mapper will call the mapFromObject()
method to get the resulting
MoneyDto
. The mapping will be done even if your Money
object is deeply
buried within the object you are mapping from.
Mapping to Another Object
You can also get the reverse of the above by implement the
MapToObjectInterface
and create the mapToObject()
method.
namespace App\Dto;
use Brick\Money\Money;
use Rekalogika\Mapper\Context\Context;
use Rekalogika\Mapper\MethodMapper\MapToObjectInterface;
use Rekalogika\Mapper\MethodMapper\SubMapperInterface;
final class MoneyDto implements MapToObjectInterface
{
// ...
public function mapToObject(
object|string $target,
SubMapperInterface $mapper,
Context $context
): object {
return Money::of($this->amount, $this->currency);
}
}
SubMapper
The $mapper
parameter in the mapFromObject()
and mapToObject()
methods
provides you with the SubMapper. Read more about the sub mapper in the
SubMapper chapter.