consistence-community/consistence-doctrine

Consistence 库与 Doctrine ORM 集成

2.1.4 2023-06-15 17:06 UTC

This package is auto-updated.

Last update: 2024-09-15 19:47:41 UTC


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 枚举。有两件重要的事情需要注意

  1. type="string_enum"ORM\Column 中 - 这将用于将值映射到您的数据库,这意味着如果您有一个基于字符串的枚举(参见 Sex 中的值),请使用 string_enum

您可以为 ORM\Column 指定任何其他参数,就像您通常做的那样(nullability,length...)。

还有 integer_enumfloat_enumboolean_enum,可以分别用于其类型。

  1. @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,它将负责集成。

  1. 使用 Composer 安装包 consistence-community/consistence-doctrine
composer require consistence-community/consistence-doctrine
  1. 注册 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() 可能已经在您的应用程序的某个地方被调用,所以在添加之前请检查。

  1. 注册 postLoad 监听器:

您需要注册 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)
);

如果没有,只需创建一个新的实例并将其传递给构造函数。

这就完成了,您已经准备好出发了!