denismitr / laravel-event-recorder
Laravel 事件记录器
Requires
- php: >=7.0
- denismitr/laravel-json-attributes: ^1.0
- illuminate/console: ~5.5.0|~5.6.0
- illuminate/database: ~5.5.0|~5.6.0
- illuminate/events: ~5.5.0|~5.6.0
- illuminate/support: ~5.5.0|~5.6.0
Requires (Dev)
- mockery/mockery: ^1.1
- orchestra/testbench: ^3.5
- phpunit/phpunit: ^6.5
This package is auto-updated.
Last update: 2024-09-23 09:10:16 UTC
README
作者
Denis Mitrofanov
要求
PHP 7.0 或更高版本,MYSQL 5.7 或更高版本,或 POSTGRES 可能任何 9.* 版本或更高版本都可以,Laravel >=5.5
版本 2.x
概述
任何需要记录到数据库的类必须实现 Denismitr\EventRecorder\Contracts\ShouldBeRecorded
接口或扩展 Denismitr\EventRecorder\ConditionallyRecordable
抽象类,该抽象类可以在某些条件下记录事件。两种方式都强制实现两个方法 getProperties(): array
和 getDescription(): string
,如果扩展抽象类,还可以在需要跳过某些条件下的事件记录时覆盖方法。由 getProperties()
返回的属性是您希望记录/持久化的给定事件的任意 键值对 数组(见下例)。getDescription(): string
只是事件的简单文本形式。属性以 json 格式存储,描述是 VARCHAR 512(可配置)字符串字段。
安装
使用 composer composer require denismitr/laravel-event-recorder
在 Laravel 5.5 中,服务提供程序将自动注册。但您也可以在 config/app.php
文件中手动注册
'providers' => [
// ...
Denismitr\EventRecorder\EventRecorderServiceProvider::class,
];
您可以使用以下命令发布迁移
php artisan vendor:publish --provider="Denismitr\EventRecorder\EventRecorderServiceProvider" --tag="migrations"
您可以使用以下命令发布配置文件
php artisan vendor:publish --provider="Denismitr\EventRecorder\EventRecorderServiceProvider" --tag="config"
在迁移已发布并且您对配置满意后,运行迁移: php artisan migrate
使用方法
让我们假设我们有一个 MoneyAddedToWallet
事件
class MoneyAddedToWallet implements ShouldBeRecorded { /** * @var Wallet */ public $wallet; /** * @var int */ public $amount; /** * MoneyAddedToWallet constructor. * @param Wallet $wallet * @param int $amount */ public function __construct(Wallet $wallet, int $amount) { $this->wallet = $wallet; $this->amount = $amount; } public function getProperties(): array { return [ 'wallet_id' => $this->wallet->id, 'amount' => $this->amount, 'user_id' => $this->wallet->user_id, 'operation' => 'credit', ]; } public function getDescription(): string { return vsprintf("User with ID %s added %d to the wallet with ID %s", [ $this->wallet->user_id, $this->amount, $this->wallet->id, ]); } }
或者另一个继承选项
class MoneyAddedToWallet extends ConditionallyRecordable { use TriggeredByUser; /** * @var Wallet */ public $wallet; /** * @var int */ public $amount; /** * @var bool */ public $byAdmin; /** * MoneyAddedToWallet constructor. * @param Wallet $wallet * @param int $amount * @param bool $byAdmin */ public function __construct(Wallet $wallet, int $amount, $byAdmin = false) { $this->wallet = $wallet; $this->amount = $amount; $this->byAdmin = $byAdmin; } public function getProperties(): array { return [ 'wallet_id' => $this->wallet->id, 'amount' => $this->amount, 'user_id' => $this->getTriggeredById(), 'operation' => 'credit', ]; } public function getDescription(): string { return vsprintf("User with ID %s added $%d to the wallet with ID %s", [ $this->getTriggeredById(), $this->amount, $this->wallet->id, ]); } // This method overrides default implementation // that always return false public function shouldBeSkipped(): bool { // skip events generated by admin action return !! $this->byAdmin; } }
在它触发后。会在 recorded_events
表中创建一条记录。以下是从测试文件中摘录的内容,希望能解释正在发生的事情。
event(new MoneyAddedToWallet($this->wallet, 1234)); $recordedEvent = RecordedEvent::first(); $this->assertEquals(MoneyAddedToWallet::class, $recordedEvent->class); // json properties $this->assertEquals(1234, $recordedEvent->properties->get('amount')); $this->assertEquals($this->wallet->id, $recordedEvent->properties->get('wallet_id')); $this->assertEquals($this->user->id, $recordedEvent->properties->get('user_id')); $this->assertEquals('credit', $recordedEvent->properties->get('operation')); $this->assertDatabaseHas('recorded_events', [ 'name' => 'money_added_to_wallet', 'class' => 'Denismitr\EventRecorder\Tests\Stubs\Events\MoneyAddedToWallet', 'description' => "User with ID {$this->user->id} added 1234 to the wallet with ID {$this->wallet->id}" ]);
有两点需要注意
- 首先 - 此软件包使用依赖项 denismitr/laravel-json-attributes 以优雅的方式处理 JSON 属性。有关更多信息,请参阅 文档。
- 其次 - 在
recorded_events
中有一个名为 name 的列,它是通过完整的事件类名以 snake cased class name(不带命名空间)的形式生成的。
触发条件
截至版本 1.0,软件包支持记录触发事件的用户的 ID,并从版本 2.0 开始,您还可以存储用户的任意属性。如果您在要记录的事件类中使用特质 Denismitr\EventRecorder\TriggeredByUser
,当事件发生时,当前登录用户的 ID 将与其他数据一起保存。在 recorded_events
中用于此的数据库列称为 triggered_by_id
。在 RecordedEvents
模型中定义了 Laravel 的 belongsTo
关联。这样,您可以检索触发事件的用户的实例。
自2.0版本起,在模式中添加了一个triggered_by_properties
列,并且增加了一个新的特质Denismitr\EventRecorder\Traits\CanTriggerEvents
,该特质负责从用户数据中选择并过滤以存储到该列中。使用此特质是可选的
。默认情况下,它将持久化给定用户
模型的所有属性,除了标准Laravel
用户模型中包含的$hidden
数组中的那些属性。您可以通过在用户模型中添加public $eventAttributeBlacklist = [];
并填充要排除的属性来进一步控制不应持久化的属性。
由于此特质仅负责将用户数据作为json存储,因此不使用它不会阻止将用户ID作为triggered_by_id
存储,这完全是Denismitr\EventRecorder\TriggeredByUser
和使用的活动类的责任。
配置
配置文件的内容如下
return [ 'triggered_by_id_type' => 'unsignedInteger', 'triggered_by_class' => 'App\User', 'max_length' => [ 'event_name' => 100, 'event_description' => 512, ] ];
如果您需要更改这些属性中的某些属性,请确保在实际上运行php artisan migrate
之前进行更改,否则您将不得不执行php artisan migrate:fresh
,或者如果已经不可能,您将不得不手动创建更改您数据库模式逻辑。