marble / entity-manager
PHP 的无 ORM 实体生命周期管理器。
0.5.0
2023-12-30 22:02 UTC
Requires
- php: ^8.1
- doctrine/instantiator: ^1.4
- ocramius/generated-hydrator: ^4.2
- psr/event-dispatcher: ^1.0
- sebastian/comparator: ^4.0
- sebastian/exporter: ^4.0
Requires (Dev)
- mockery/mockery: ^1.4
- phpunit/phpunit: ^9.5
- psr/container: ^2.0
- symfony/uid: ^5.3
- vimeo/psalm: ^4.16
Suggests
- psr/container: If you want to use the provided container-aware repository factory.
- symfony/uid: If you want to use the provided ULID implementation of the Identifier interface.
README
介绍
此库提供了许多 ORM 框架的一些优秀功能——实体管理器、工作单元、身份映射、仓库工厂、查询缓存——而不包含对象关系映射本身。具体实现从您所使用的持久化层读取和写入实体数据由您自己决定。
安装
使用 Composer 安装: composer require marble/entity-manager
此库需要 PHP 8.1。
如何使用
- 您所有的实体类都应该实现
Entity
接口。对于标识符,您可以使用提供的SimpleId
或Ulid
类,或任何其他实现Identifier
接口的实现。 - 为从应用程序代码或其他读取器获取的每个实体类创建一个实现
EntityReader
的类。有关详细信息,请参阅获取。 - 对于每个实体类,创建一个实现
EntityWriter
的类,除非此类实体总是由其他写者写入和删除。有关详细信息,请参阅持久化和删除。
持久化
- 同一实体类层次结构中的多个实体永远不能有相同的标识符。如果新实体还没有标识符,这是可以的,但一旦实体被持久化,它就必须有一个标识符。
- 通过将已知实体排序,以使得给定实体的关联都排在实体本身之上,来计算刷新顺序。因此,在
EntityWriter::write
中持久化实体时,其关联实体已经传递给它们的写者。此算法不允许循环实体关联。 - 您可以使用写者持久化其自身的实体以及特定的关联实体(“子实体”),例如,聚合根的写者也持久化聚合中的其他实体。确保在传递的
WriteContext
上调用markPersisted
以让工作单元知道这些确实已经持久化。EntityIoProvider::getWriter
可以返回null
,对于总是由其他写者持久化的实体类。 - 当您需要在刷新顺序的稍后阶段将实体写入或删除留给父实体的写者时,您的实体写者应该抛出
EntitySkippedException
。库将在刷新结束时检查是否已完成所有必要的写入和删除。
获取
- 通过从实体管理器获取其实体仓库,并将任何类型的对象传递给
fetch*
方法之一来获取实体。该对象表示要执行的查询。它将被传递给实体读取器,您应该适当地处理它。一个特殊情况是实现Identifier
接口的对象;这些对象仅允许在fetchOne
方法中。 - 获取实体时,使用传递的
ReadContext
访问其他仓库,并通过它们获取关联实体。任何关联的子实体都将替换为其在身份映射中存在的等效实体。因此,即使在嵌套关联中,特定实体的实例也只有一个。 - 您可以通过让
EntityIoProvider::getCustomRepositoryClass
返回自定义仓库类的名称,为特定实体类使用自定义仓库。该自定义仓库必须继承自DefaultRepository
,并且必须使用其父类的fetchOne
和fetchMany
方法。EntityReader
应继续处理所有实际的读取操作(例如数据库交互);自定义仓库允许您将查询构建的细节从领域代码中隐藏起来。自定义仓库还可以简化依赖注入,例如,仅向服务中注入它所需的特定仓库,而不是实体管理器。
删除
- 您可以使用写入器来删除自己的实体以及关联的子实体,无论是显式删除还是通过数据库级别的级联规则删除。请确保在传递的
DeleteContext
上调用markRemoved
,以便让工作单元知道这些实体确实已被删除。 - 已删除的实体将从身份映射中删除。再次检索同一实体将返回一个新实例。