elegantweb / laravel-transactional-events
Laravel 框架的事务性事件。
Requires
- php: ^7.4|^8.0
- laravel/framework: ^8.0|^9.0|^10.0
Requires (Dev)
- orchestra/testbench: ^6.0|^7.0|^8.0
- phpunit/phpunit: ^9.6
README
Laravel 框架的事务性事件。
安装
composer require elegantweb/laravel-transactional-events
为什么?
下面是一个示例
DB::transaction(function () { $post = Post::create(['title' => 'An Awesome Post!']); event(new PostCreated($post)); $post->categories()->create(['name' => 'Blog']); });
乍一看,一切似乎都很正常,但这里有一个大问题!
想象一下,我们在 PostCreated
事件中发送通知,看看会发生什么
情况 1:通知发送失败,可能抛出异常,事务将回滚,创建的帖子将从数据库中删除。实际上发生的情况是,由于通知失败,我们的帖子被删除了。问问自己,“这是我想看到的吗?!🤔”大多数情况下,我们不想因为通知失败而删除帖子!
情况 2:假设 PostCreated
事件成功分派而没有错误。但由于某些数据库或应用程序问题,我们在尝试为我们的帖子创建类别时遇到了错误(多么不幸啊!!! 😩),在这种情况下,事务将失败,帖子将从数据库中删除。到目前为止一切还好,但你知道吗?!我们已经在 PostCreated
事件中为已不存在的帖子发送了通知!😱
解决方案:这里的解决方案是使事件在事务提交后分派。使用这个包,你可以使事件成为事务性的,因此事件将延迟到事务提交时再处理。
用法
该包默认启用。你需要做的是将你的事件变为事务性的。
使用事务接口
使一个事件成为事务性的一种方法是实现 Elegant\Events\TransactionalEvent
接口。下面是一个示例
use Elegant\Events\TransactionalEvent; class MyAwesomeEvent implements TransactionalEvent { }
现在 MyAwesomeEvent
类是事务性的,并且每次你分派它时,它都将由该包处理。
使用配置
另一种方法是使用配置文件。这样,你可以使一组事件成为事务性的。
首先发布默认配置文件
php artisan vendor:publish --tag="laravel-transactional-events-config"
我们有两种选择,include
和 exclude
。
使用 include
,你可以使某个命名空间下的事件类或事件组成为事务性的。
默认情况下,我们有 App\Events
命名空间,这将导致 App\Events
命名空间下的所有事件都变为事务性的。
return [ 'include' => [ 'App\Events', ], ];
exclude
选项与 include
选项相反,你可以排除某个命名空间下的事件类或事件组使其不成为事务性的。
下面的示例将导致 App\Events
命名空间下的所有事件都变为事务性,除了 App\Events\MyAwesomeEvent
类。
return [ 'include' => [ 'App\Events', ], 'exclude' => [ 'App\Events\MyAwesomeEvent', ], ];