brokalia/doctrine-entity-generator

从领域实体生成 doctrine 实体和映射器

0.1.0 2022-11-18 23:17 UTC

This package is auto-updated.

Last update: 2024-09-20 13:33:44 UTC


README

这个 Symfony 扩展包提供了一个控制台命令,用于从领域实体类生成具有映射属性的 doctrine 实体和映射器类。

然后您可以在领域和应用层使用领域实体,并将其映射到 doctrine 实体以实现持久化。

使用方法

bin/console doctrine-generator:entity "App\Domain\MyDomainEntity"

约定

doctrine 实体的主键必须是领域实体的 "id" 属性。如果领域实体中没有 "id" 属性,则 doctrine 实体将没有主键。

class MyDomainEntity {
    private string $id; // Will be the doctrine primary key
}

class DoctrineMyDomainEntity {
    #[ORM\Column(type: 'string')]
    #[ORM\Id]
    public string $id;
}

完整示例

假设有 MyDomainEntity 并包含一些值对象

// src/Domain/MyDomainEntity.php
class MyDomainEntity {
    public function __construct(
        private MyDomainEntityId $id,
        private SampleValueObject $valueObject,
    ) {
    }

    public function getId(): MyDomainEntityId
    {
        return $this->id;
    }

    public function getValueObject(): SampleValueObject
    {
        return $this->valueObject;
    }
}
// src/Domain/MyDomainEntityId.php
class MyDomainEntityId
{
    public function __construct(private string $value)
    {
    }

    public function getValue(): string
    {
        return $this->value;
    }
}
// src/Domain/EntityId.php
class SampleValueObject
{
    public function __construct(
        private string $firstAttribute, 
        private int $secondAttribute
    ) {
    }

    public function getFirstAttribute(): string
    {
        return $this->firstAttribute;
    }

    public function getSecondAttribute(): int
    {
        return $this->secondAttribute;
    }
}

生成 doctrine 实体和映射器,用于在领域和 doctrine 实体之间进行映射

// src/Infrastructure/Persistence/DoctrineMyDomainEntity.php
class DoctrineMyDomainEntity
{
    #[ORM\Column(type: 'string')]
    #[ORM\Id]
    public string $id;

    #[ORM\Column(type: 'string')]
    public string $valueObject_firstAttribute;

    #[ORM\Column(type: 'integer')]
    public int $valueObject_secondAttribute;
}
// src/Infrastructure/Persistence/DoctrineMyDomainEntityMapper.php
class DoctrineMyDomainEntityMapper
{
    public function fromDomain(
        MyDomainEntity $domainEntity,
        ?DoctrineMyDomainEntity $doctrineEntity,
    ): DoctrineMyDomainEntity {
        $doctrineEntity = $doctrineEntity ?? new DoctrineMyDomainEntity();

        $doctrineEntity->id = $domainEntity->getId()->getValue();
        $doctrineEntity->valueObject_firstAttribute = $domainEntity->getValueObject()->getFirstAttribute();
        $doctrineEntity->valueObject_secondAttribute = $domainEntity->getValueObject()->getSecondAttribute();

        return $doctrineEntity;
    }

    public function toDomain(DoctrineMyDomainEntity $doctrineEntity): MyDomainEntity
    {
        $reflector = new ReflectionClass(MyDomainEntity::class);
        $constructor = $reflector->getConstructor();
        if (!$constructor) {
            throw new RuntimeException('No constructor');
        }
        $object = $reflector->newInstanceWithoutConstructor();
        $constructor->invoke(
            $object,
            new MyDomainEntityId($doctrineEntity->id),
            new SampleValueObject(
                $doctrineEntity->valueObject_firstAttribute, 
                $doctrineEntity->valueObject_secondAttribute
            ),
        );
        return $object;
    }
}

现在您可以使用 doctrine 创建领域实体的存储库,并使用映射器持久化实体。

class MyDomainEntityRepository {
    public function __construct(
        private EntityManagerInterface $entityManager, 
        private DoctrineMyDomainEntityMapper $mapper,
    ) {
    }
    
    public function save(MyDomainEntity $entity): void
    {
        // Get previous existent doctrine entity if exists for update cases
        $existentDoctrineEntity = $this->findDoctrineEntity($entity->getId()->getValue());
            
        // Map domain entity to doctrine entity
        $doctrineEntity = $this->mapper->fromDomain(
            $entity, 
            $existentDoctrineEntity ?? new DoctrineMyDomainEntity()
        );
        
        // Persist
        $this->entityManager->persist($doctrineEntity);
        $this->entityManager->flush();
    }
    
    public function findById(MyDomainEntityId $id): ?MyDomainEntity 
    {
        // Get doctrine entity
        $doctrineEntity = $this->findDoctrineEntity($id->getValue());
            
        if (!$doctrineEntity) {
            return null;
        }
        
        // Return domain entity mapped
        return $this->mapper->toDomain($doctrineEntity);
    }
    
    private function findDoctrineEntity(string $id): ?DoctrineMyDomainEntity
    {
        return $this->entityManager->getRepository(DoctrineMyDomainEntity::class)->find($id);
    }
}

安装

请确保已全局安装 Composer,如 Composer 文档中的 安装章节 所述。

使用 Symfony Flex 的应用程序

打开命令行,进入您的项目目录,然后执行以下命令

$ composer require --dev brokalia/doctrine-entity-generator

不使用 Symfony Flex 的应用程序

步骤 1: 下载 Bundle

打开命令行,进入您的项目目录,然后执行以下命令以下载此 Bundle 的最新稳定版本

$ composer require --dev brokalia/doctrine-entity-generator

步骤 2: 启用 Bundle

然后,通过将其添加到项目 config/bundles.php 文件中注册的 Bundle 列表来启用该 Bundle

// config/bundles.php

return [
    // ...
    Brokalia\DoctrineEntityGenerator\DoctrineEntityGeneratorBundle::class => ['dev' => true],
];