consistence-community / consistence-doctrine
Consistence 库与 Doctrine ORM 集成
Requires
- php: ~7.4 || ~8.0
- consistence-community/consistence: ~2.1
- doctrine/annotations: ~1.7 || ^2.0
- doctrine/orm: ^2.10.0
Requires (Dev)
- consistence-community/coding-standard: 3.11.1
- doctrine/cache: ^1.11
- doctrine/persistence: ^1.3.5 || ^2.0
- phing/phing: 2.17.0
- php-parallel-lint/php-parallel-lint: 1.3.1
- phpunit/phpunit: 9.5.10
Replaces
README
此包是基于 consistence/consistence-doctrine
的分支,由社区维护,以支持新的 PHP 版本。
此库提供了 Consistence 值对象与 Doctrine ORM 的集成,以便您可以在实体中使用它们。
目前,所需的唯一集成是 枚举,请参见下面的示例。
使用方法
枚举 代表一组预定义的值,当然,您也会希望将这些值存储在您的数据库中。由于 枚举
是对象,而您只想存储表示的值,因此必须进行某种映射。
您可以在以下示例中看到它,其中您想为您的 User
存储性别
<?php namespace Consistence\Doctrine\Example\User; class Sex extends \Consistence\Enum\Enum { public const FEMALE = 'female'; public const MALE = 'male'; }
现在您可以在 User
实体中使用 Sex
枚举。有两件重要的事情需要注意
type="string_enum"
在ORM\Column
中 - 这将用于将值映射到您的数据库,这意味着如果您有一个基于字符串的枚举(参见Sex
中的值),请使用string_enum
您可以为 ORM\Column
指定任何其他参数,就像您通常做的那样(nullability,length...)。
还有 integer_enum
,float_enum
和 boolean_enum
,可以分别用于其类型。
@Enum(class=Sex::class)
- 这将用于在从数据库加载值时重新构造Sex
枚举对象
class
注解参数使用与其他 Doctrine 注解相同的命名空间解析过程,因此在实际上它与在关联映射中指定 targetEntity
相同。
<?php namespace Consistence\Doctrine\Example\User; use Consistence\Doctrine\Enum\EnumAnnotation as Enum; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity() */ class User extends \Consistence\ObjectPrototype { // ... /** * @Enum(class=Sex::class) * @ORM\Column(type="string_enum", nullable=true) * @var \Consistence\Doctrine\Example\User\Sex|null */ private $sex; // ... public function __construct( // ... Sex $sex = null // ... ) { // ... $this->sex = $sex; // ... } // ... }
现在一切准备就绪,当您调用 flush
时,只有 female
将被保存
<?php namespace Consistence\Doctrine\Example\User; $user = new User( // ... Sex::get(Sex::FEMALE) // ... ); /** @var \Doctrine\ORM\EntityManager $entityManager */ $entityManager->persist($user); // when persisting User::$sex to database, `female` will be saved $entityManager->flush();
并且当您从数据库检索实体时,您将再次收到 Sex
枚举对象
<?php namespace Consistence\Doctrine\Example\User; /** @var \Doctrine\ORM\EntityManager $entityManager */ $user = $entityManager->find(User::class, 1); var_dump($user->getSex()); /* class Consistence\Doctrine\Example\User\Sex#5740 (1) { private $value => string(6) "female" } */
这意味着对象的 API 是对称的(您得到与您设置相同的类型),您可以开始利用 枚举 的优势,例如确保您得到的是有效的值,并且可以定义在表示值之上的方法。
安装
如果您正在使用 Symfony,可以使用
consistence-community/consistence-doctrine-symfony
,它将负责集成。
composer require consistence-community/consistence-doctrine
- 注册 Doctrine DBAL 类型 和 注解
<?php use Consistence\Doctrine\Enum\Type\BooleanEnumType; use Consistence\Doctrine\Enum\Type\FloatEnumType; use Consistence\Doctrine\Enum\Type\IntegerEnumType; use Consistence\Doctrine\Enum\Type\StringEnumType; use Doctrine\Common\Annotations\AnnotationRegistry; use Doctrine\DBAL\Types\Type as DoctrineType; // path to your Composer autoload file $loader = require __DIR__ . '/../vendor/autoload.php'; // register loading of custom annotations // if you are already using Doctrine annotations you probably won't need this AnnotationRegistry::registerLoader([$loader, 'loadClass']); // register Doctrine DBAL types DoctrineType::addType(BooleanEnumType::NAME, BooleanEnumType::class); // boolean_enum DoctrineType::addType(FloatEnumType::NAME, FloatEnumType::class); // float_enum DoctrineType::addType(IntegerEnumType::NAME, IntegerEnumType::class); // integer_enum DoctrineType::addType(StringEnumType::NAME, StringEnumType::class); // string_enum
此步骤包含具有全局影响的静态调用,因此建议将它们放在启动文件(通常是现在注册 Composer 自动加载器的地方)中,该文件在应用启动时运行或包含。
如果您已经使用了 Doctrine 注解,则 AnnotationRegistry::registerLoader()
可能已经在您的应用程序的某个地方被调用,所以在添加之前请检查。
您需要注册 EnumPostLoadEntityListener
,它需要 \Doctrine\Common\Annotations\Reader
。如果您使用 注解 Doctrine 映射,则可以使用以下方式使用相同的读取器
<?php use Consistence\Doctrine\Enum\EnumPostLoadEntityListener; use Doctrine\Common\Cache\ArrayCache; use Doctrine\ORM\Events; /** @var \Doctrine\ORM\EntityManager $entityManager */ /** @var \Doctrine\ORM\Mapping\Driver\AnnotationDriver $annotationDriver */ $annotationDriver = $entityManager->getConfiguration()->getMetadataDriverImpl(); $annotationReader = $annotationDriver->getReader(); // make sure to use the most appropriate cache for given environment to get the best performance $cache = new ArrayCache(); $entityManager->getEventManager()->addEventListener( Events::postLoad, new EnumPostLoadEntityListener($annotationReader, $cache) );
如果没有,只需创建一个新的实例并将其传递给构造函数。
这就完成了,您已经准备好出发了!