PHP code example of symfonycasts / micro-mapper

1. Go to this page and download the library: Download symfonycasts/micro-mapper library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

symfonycasts / micro-mapper example snippets


use App\Entity\Dragon;
use App\DTO\DragonDTO;

#[AsMapper(from: Dragon::class, to: DragonDTO::class)]
class DragonEntityToDtoMapper implements MapperInterface
{
    public function load(object $from, string $toClass, array $context): object
    {
        $entity = $from;

        return new DragonDTO($entity->getId());
    }

    public function populate(object $from, object $to, array $context): object
    {
        $entity = $from;
        $dto = $to;

        $dto->name = $entity->getName();
        $dto->firePower = $entity->getFirePower();

        return $dto;
    }
}

$dragon = $dragonRepository->find(1);
$dragonDTO = $microMapper->map($dragon, DragonDTO::class);

namespace App\Mapper;

use App\Entity\Dragon;
use App\ApiResource\DragonApi;
use Symfonycasts\MicroMapper\AsMapper;
use Symfonycasts\MicroMapper\MapperInterface;

#[AsMapper(from: Dragon::class, to: DragonApi::class)]
class DragonEntityToApiMapper implements MapperInterface
{
    public function load(object $from, string $toClass, array $context): object
    {
        $entity = $from;
        assert($entity instanceof Dragon); // helps your editor know the type

        return new DragonApi($entity->getId());
    }

    public function populate(object $from, object $to, array $context): object
    {
        $entity = $from;
        $dto = $to;
        // helps your editor know the types
        assert($entity instanceof Dragon);
        assert($dto instanceof DragonApi);

        $dto->name = $entity->getName();
        $dto->firePower = $entity->getFirePower();

        return $dto;
    }
}



namespace App\Controller;

use App\Entity\Dragon;
use App\ApiResource\DragonApi;
use Symfonycasts\MicroMapper\MicroMapperInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;

class DragonController extends AbstractController
{
    #[Route('/dragons/{id}', name: 'api_dragon_get_collection')]
    public function index(Dragon $dragon, MicroMapperInterface $microMapper)
    {
        $dragonApi = $microMapper->map($dragon, DragonApi::class);

        return $this->json($dragonApi);
    }
}

namespace App\Mapper;

use App\ApiResource\DragonApi;
use App\Entity\Dragon;
use App\Repository\DragonRepository;
use Symfonycasts\MicroMapper\AsMapper;
use Symfonycasts\MicroMapper\MapperInterface;

#[AsMapper(from: DragonApi::class, to: Dragon::class)]
class DragonApiToEntityMapper implements MapperInterface
{
    public function __construct(private DragonRepository $dragonRepository)
    {
    }

    public function load(object $from, string $toClass, array $context): object
    {
        $dto = $from;
        assert($dto instanceof DragonApi);

        return $dto->id ? $this->dragonRepository->find($dto->id) : new Dragon();
    }

    public function populate(object $from, object $to, array $context): object
    {
        $dto = $from;
        $entity = $to;
        assert($dto instanceof DragonApi);
        assert($entity instanceof Dragon);

        $entity->setName($dto->name);
        $entity->setFirePower($dto->firePower);

        return $entity;
    }
}

// ...

#[AsMapper(from: Treasure::class, to: TreasureApi::class)]
class TreasureEntityToApiMapper implements MapperInterface
{
    public function load(object $from, string $toClass, array $context): object
    {
        return new TreasureApi($from->getId());
    }

    public function populate(object $from, object $to, array $context): object
    {
        $entity = $from;
        $dto = $to;

        // ... map all the properties

        return $dto;
    }
}

namespace App\Mapper;

// ...
use App\ApiResource\TreasureApi;
use Symfonycasts\MicroMapper\MicroMapperInterface;

#[AsMapper(from: Dragon::class, to: DragonApi::class)]
class DragonEntityToApiMapper implements MapperInterface
{
    public function __construct(private MicroMapperInterface $microMapper)
    {
    }

    // load() is the same

    public function populate(object $from, object $to, array $context): object
    {
        $entity = $from;
        $dto = $to;
        // ... other properties

        $treasuresApis = [];
        foreach ($entity->getTreasures() as $treasureEntity) {
            $treasuresApis[] = $this->microMapper->map($treasureEntity, TreasureApi::class, [
                MicroMapperInterface::MAX_DEPTH => 1,
            ]);
        }
        $dto->treasures = $treasuresApis;

        return $dto;
    }
}

// ...

#[AsMapper(from: Treasure::class, to: TreasureApi::class)]
class TreasureEntityToApiMapper implements MapperInterface
{
    public function __construct(private MicroMapperInterface $microMapper)
    {
    }

    // load()

    public function populate(object $from, object $to, array $context): object
    {
        $entity = $from;
        $dto = $to;
        // ... map all the properties
        
        $dto->dragon = $this->microMapper->map($entity->getDragon(), DragonApi::class, [
            MicroMapperInterface::MAX_DEPTH => 1,
        ]);

        return $dto;
    }
}

$dto->dragon = $this->microMapper->map($dragonEntity, DragonApi::class, [
    MicroMapperInterface::MAX_DEPTH => ???,
]);


// ...

#[AsMapper(from: DragonApi::class, to: Dragon::class)]
class DragonApiToEntityMapper implements MapperInterface
{
    // ...

    public function populate(object $from, object $to, array $context): object
    {
        $dto = $from;
        $entity = $to;
        // ...

        $treasureEntities = new ArrayCollection();
        foreach ($dto->treasures as $treasureApi) {
            $treasureEntities[] = $this->microMapper->map($treasureApi, Treasure::class, [
                // depth=0 because we really just need to load/query each Treasure entity
                MicroMapperInterface::MAX_DEPTH => 0,
            ]);
        }

        // !!!!! THIS WILL NOT WORK !!!!!
        $entity->setTreasures($treasureEntities);

        return $entity;
    }
}


// ...
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;

#[AsMapper(from: DragonApi::class, to: Dragon::class)]
class DragonApiToEntityMapper implements MapperInterface
{
    public function __construct(
        private MicroMapperInterface $microMapper,
        private PropertyAccessorInterface $propertyAccessor
    )
    {
    }

    // ...

    public function populate(object $from, object $to, array $context): object
    {
        $dto = $from;
        $entity = $to;
        // ...

        $treasureEntities = [];
        foreach ($dto->treasures as $treasureApi) {
            $treasureEntities[] = $this->microMapper->map($treasureApi, Treasure::class, [
                MicroMapperInterface::MAX_DEPTH => 0,
            ]);
        }

        // this will call the addTreasure() and removeTreasure() methods
        $this->propertyAccessor->setValue($entity, 'treasures', $treasureEntities);

        return $entity;
    }
}

$microMapper = new MicroMapper([]);
$microMapper->addMapperConfig(new MapperConfig(
    from: Dragon::class,
    to: DragonApi::class,
    fn() => new DragonEntityToApiMapper($microMapper)
));
$microMapper->addMapperConfig(new MapperConfig(
    from: DragonApi::class,
    to: Dragon::class,
    fn() => new DragonApiToEntityMapper($microMapper)
));

// now it's ready to use!