enumeum/doctrine-enums

Doctrine 扩展,用于管理 PostgreSQL 中的枚举类型

2.1.0 2023-05-06 12:20 UTC

This package is auto-updated.

Last update: 2024-09-07 19:29:10 UTC


README

本包包含 Doctrine ORM 和 DBAL 的扩展,提供 PostgreSQL 数据库中枚举类型的管理功能。是的,数据库中的枚举类型是坏做法,你应该避免使用它们。但有时数据库管理需要枚举类型作为对某些字段的简单约束。本包提供了一种透明的方法,将 PHP 枚举作为数据库类型添加,并在 Doctrine 实体中与适当的字段一起使用。

要求

最低 PHP 版本是 8.1。

安装

composer require enumeum/doctrine-enums

使用方法

PHP 枚举属性

  • #[Enumeum\DoctrineEnum\Attribute\EnumType(name: 'type_name')] 这个属性表示这个枚举是数据库类型。默认情况下,它将在数据库中创建具有其自己的 case 的类型。

枚举设置

<?php
namespace App\Enums;

use Enumeum\DoctrineEnum\Attribute\EnumType;

#[EnumType(name: 'status_type')]
enum StatusType: string
{
    case STARTED = 'started';
    case PROCESSING = 'processing';
    case FINISHED = 'finished';
}

实体设置

请注意,实体的配置与通常的配置没有区别。Doctrine 支持 "enumType" 属性,并透明地转换它。

<?php
namespace App\Entities;

use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use App\Enum\StatusType;

/**
 * @ORM\Entity
 * @ORM\Table(name="entity")
 */
#[ORM\Entity]
#[ORM\Table(name: 'entity')]
class Entity
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     */
    #[ORM\Id]
    #[ORM\Column(type: Types::INTEGER)]
    private int $id;

    /**
     * @ORM\Column(type="string", enumType=StatusType::class, options={"comment":"Comment"})
     */
    #[ORM\Column(type: Types::STRING, enumType: StatusType::class, options: ['comment' => 'Comment'])]
    private StatusType $status;

    public function __construct(
        int $id,
        StatusType $status,
    ) {
        $this->id = $id;
        $this->status = $status;
    }

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

    public function getStatus(): StatusType
    {
        return $this->status;
    }
}

DBAL 配置

<?php

namespace App;

use Enumeum\DoctrineEnum\Definition\DefinitionRegistryLoader;
use Enums\BaseStatusType;

$enumClassNames = [
    BaseStatusType::class,
    // ...
];

$enumDirPaths = [
    [
        'path' => __DIR__.'/../Enums',
        'namespace' => 'App\Enums',
    ]
    // ...
];

$loader = DefinitionRegistryLoader::create(new EnumClassLocator([]), $enumClassNames, $enumDirPaths);

可以通过适当的方法添加一个或多个额外的类型或目录

$loader->loadType(BaseStatusType::class);
$loader->loadTypes([BaseStatusType::class]);

$loader->loadDir([
    'path' => __DIR__.'/../Enums',
    'namespace' : 'App\Enums',
]);
$loader->loadDirs([
    [
        'path' => __DIR__.'/../Enums',
        'namespace' : 'App\Enums',
    ],
]);

填充加载器为 Enumeum\DoctrineEnum\Definition\DefinitionRegistry 实例提供枚举定义的集合。每次调用都会创建一个新的 Registry 实例。

$registry = $loader->getRegistry();

DBAL 模式操作需要加载新的类型,因此使用特殊的 Enumeum\DoctrineEnum\Type\TypeRegistryLoader

TypeRegistryLoader::load($registry->getDefinitions());

下一步是创建 Enumeum\DoctrineEnum\EnumTool 并使用它来生成数据库枚举持久化或直接更新数据库的 SQL 查询。

<?php

namespace App;

use Enumeum\DoctrineEnum\EnumTool;

$tool = EnumTool::create($registry, $doctrineDbalConnection);

// Updates database with configured enums
$tool->createSchema();
// ... OR generates SQL queries for update 
$sql = $tool->getCreateSchemaSql();

ORM 配置

ORM 部分只需要将 Enumeum\DoctrineEnum\EventSubscriber\PostGenerateSchemaSubscriber 添加到 Doctrine 的 EventManager。

<?php

namespace App;

use Doctrine\Common\EventManager;
use Doctrine\ORM\EntityManager;
use Enumeum\DoctrineEnum\EnumUsage\TableColumnRegistry;
use Enumeum\DoctrineEnum\EventSubscriber\PostGenerateSchemaSubscriber;

$evm = new EventManager();
$em = EntityManager::create($params, $config, $evm);
$evm->addEventSubscriber(new PostGenerateSchemaSubscriber(
    $registry,
    new TableColumnRegistry($em->getConnection()),
));

使用方法

如果你已经更改了枚举值、结构、添加或删除类型,那么请使用 Enumeum\DoctrineEnum\EnumTool。它将生成同步配置枚举或直接更新数据库的 SQL 查询。之后,如果需要更改不仅包括枚举,还包括模式,那么请执行模式差异/更新。

运行测试

要设置和运行测试,请按照以下步骤操作

  • 安装 Docker 并确保你有 docker-composemake(可选)
  • 从项目根目录运行 make start 以在守护进程模式下启动容器(或使用 docker-compose up -d --build --remove-orphans --force-recreate
  • 通过 make console 进入容器(或使用 docker-compose exec php bash
  • 检查你是否在根目录 /var/www,如果不是,则使用以下命令导航:cd /var/www
  • 通过 composer install 安装 Composer 依赖项
  • 从容器外部使用 make test 运行测试(或使用容器内部的 bin/phpunit -c tests/

可能的未来功能

删除枚举值而不重新创建的命令。 https://postgrespro.ru/list/thread-id/2388881