bentools / doctrine-safe-events
在事务完成后触发 postPersist / postUpdate / postRemove 事件。
1.0.1
2023-01-05 13:05 UTC
Requires
- php: >=7.4
- doctrine/orm: ~2.0
Requires (Dev)
- doctrine/annotations: ~1.0
- matthiasnoback/doctrine-orm-test-service-provider: ^3.0
- pestphp/pest: ^1.22
- phpstan/phpstan: ^1.8
- squizlabs/php_codesniffer: ^3.7
- symfony/cache: ~5.4|~6.2
- symfony/var-dumper: @stable
README
Doctrine 安全 post* 事件
当对数据库服务器执行相应的 SQL 查询(INSERT / UPDATE / DELETE)时,Doctrine 的 postPersist, postUpdate 和 postRemove 事件被触发。
幕后发生的事情是,Doctrine 创建一个包装事务,运行 SQL 查询,然后提交事务。
然而,这些事件是立即触发的,例如,不是在事务完成之后,这意味着
- 如果包装事务失败,事件仍然已经触发(这意味着你信任生成的主键值,尽管它们将被回滚)
- 如果包装事务花费了一些时间(通常在行锁定期间),你将获得插入的/更新的/删除的信息,但实际上它还没有完成(这意味着如果你在事件触发后运行一些异步过程,你最终处理的是不更新的数据)
背景
这个仓库的想法确实来自于以下问题
- 一个实体被持久化,然后调用
$em->flush()
postPersist
事件监听器获取实体的 id,然后要求一个工作员通过 Symfony Messenger 进行一些异步处理- 工作员查询数据库以获取实体的 id,并得到一个
EntityNotFound
异常(尚未发生COMMIT
) - 主线程上的 flush 操作完成,并触发
postFlush
事件(但它不包含插入的/更新的/删除的实体)
我们的解决方案
如果你遇到相同类型的问题,你可以用
Bentools\DoctrineSafeEvents\SafeEvents::POST_PERSIST
(并将safePostPersist
实现为postPersist
的替代)Bentools\DoctrineSafeEvents\SafeEvents::POST_UPDATE
(并将safePostUpdate
实现为postUpdate
的替代)Bentools\DoctrineSafeEvents\SafeEvents::POST_REMOVE
(并将safePostRemove
实现为postRemove
的替代)
基本上,这个库将收集计划插入/更新/删除的实体,但它将延迟事件触发,直到发生 postFlush
。
安装
composer require bentools/doctrine-safe-events
在 Symfony 中的使用
尽管这个库没有依赖 Symfony,但你可以在你的 Symfony 项目中轻松使用它
Bentools\DoctrineSafeEvents\SafeEventsDispatcher: tags: - { name: 'doctrine.event_subscriber' } - { name: 'kernel.reset', method: 'reset' }
示例使用
declare(strict_types=1); namespace App; use Bentools\DoctrineSafeEvents\SafeEvents; use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener; use Doctrine\Persistence\Event\LifecycleEventArgs; #[AsDoctrineListener(SafeEvents::POST_PERSIST)] final class SomeListener { public function safePostPersist(LifecycleEventArgs $eventArgs): void { // ... } }
测试
composer test
许可
MIT.