spatie/laravel-eventsauce

在 Laravel 应用中使用 EventSauce

2.1.0 2020-12-02 19:53 UTC

This package is auto-updated.

Last update: 2024-09-21 18:44:43 UTC


README

在 Laravel 应用中使用 EventSauce

Latest Version on Packagist Tests Total Downloads

EventSauce 是一种简单的方法,可以将事件溯源引入 PHP 项目。此包允许 EventSauce 利用 Laravel 的迁移、模型和作业。它还可以帮助生成命令和事件的代码。如果您想在 Laravel 应用中使用 EventSauce,这个包就是您的最佳选择!

在使用 laravel-eventsauce 之前,您应该已经熟悉如何使用 EventSauce。

以下是一个如何创建一个新的聚合根和匹配的存储库的快速示例。让我们运行这个命令

php artisan make:aggregate-root "MyDomain\MyAggregateRoot"

App\MyDomain\MyAggregateRootApp\MyDomain\MyAggregateRootRepository 类将被创建。还将向您的应用程序添加一个创建 my_aggregate_root_domain_messages 的迁移。这是 MyAggregateRootRepository 的样子

namespace App\MyDomain;

use App\Domain\Account\Projectors\AccountProjector;
use App\Domain\Account\Projectors\TransactionCountProjector;
use Spatie\LaravelEventSauce\AggregateRootRepository;

/** @method \App\MyDomain\MyAggregateRoot retrieve */
class MyAggregateRootRepository extends AggregateRootRepository
{
    /** @var string */
    protected $aggregateRoot = MyAggregateRoot::class;

    /** @var string */
    protected $tableName = 'my_aggregate_root_domain_messages';

    /** @var array */
    protected $consumers = [

    ];

    /** @var array */
    protected $queuedConsumers = [

    ];
}

您可以将消费者的类名放在 $consumers 数组中。在 $queuedConsumers 数组中的消费者将通过队列作业调用并传递其消息。

MyAggregateRootRepository 可以在任何类中注入和使用。在这个例子中,我们假设您已经在 MyAggregateRoot 上手动创建了一个 performMySpecialCommand 方法。

namespace App\MyDomain;

class CommandHandler
{
    /** @var \EventSauce\EventSourcing\AggregateRootRepository */
    private $repository;

    public function __construct(MyAggregateRootRepository $repository)
    {
        $this->repository = $repository;
    }

    public function handle(object $command)
    {
        $aggregateRootId = $command->identifier();

        $aggregateRoot = $this->repository->retrieve($aggregateRootId);

        try {
            if ($command instanceof MySpecialCommand) {
               $aggregateRoot->performMySpecialCommand($command);
            } 
        } finally {
            $this->repository->persist($aggregateRoot);
        }
    }
}

支持我们

我们在创建 最佳开源包 方面投入了大量资源。您可以通过 购买我们的付费产品之一 来支持我们。

我们非常感激您从家乡寄来明信片,并提及您正在使用我们哪个包。您可以在 我们的联系页面 找到我们的地址。我们将所有收到的明信片发布在我们的 虚拟明信片墙 上。

安装

您可以通过 composer 安装此包。

composer require spatie/laravel-eventsauce

接下来,您必须发布 eventsauce 配置文件。

php artisan vendor:publish --provider="Spatie\LaravelEventSauce\EventSauceServiceProvider" --tag="config"

这是将要发布到 config/eventsauce.php 的文件内容

return [
    /*
     * Types, commands and events can be generated starting from a yaml file.
     * Here you can specify the input and the output of the code generation.
     *
     * More info on code generation here:
     * https://eventsauce.io/docs/getting-started/create-events-and-commands
     */
    'code_generation' => [
        [
            'input_yaml_file' => null,
            'output_file' => null,
        ],
    ],

    /*
     * This connection name will be used to store messages. When
     * set to null the default connection will be used.
     */
    'database_connection' => null,

    /*
     * This class will be used to store messages.
     *
     * You may change this to any class that implements
     * \EventSauce\EventSourcing\MessageRepository
     */
    'message_repository' => \Spatie\LaravelEventSauce\MessageRepository::class,

    /*
     * This class will be used to put EventSauce messages on the queue.
     *
     * You may change this to any class that extends
     * \Spatie\LaravelEventSauce\QueuedMessageJob::class
     */
    'queued_message_job' => \Spatie\LaravelEventSauce\QueuedMessageJob::class,
];

使用

生成聚合根和存储库

可以使用此命令生成聚合根和匹配的存储库

php artisan make:aggregate-root "MyDomain\MyAggregateRoot"

此命令将创建 App\MyDomain\MyAggregateRootApp\MyDomain\MyAggregateRootRepository

这是 MyAggregateRootRepository 的样子

namespace App\MyDomain;

use App\Domain\Account\Projectors\AccountProjector;
use App\Domain\Account\Projectors\TransactionCountProjector;
use Spatie\LaravelEventSauce\AggregateRootRepository;

/** @method \App\MyDomain\MyAggregateRoot retrieve */
class MyAggregateRootRepository extends AggregateRootRepository
{
    /** @var string */
    protected $aggregateRoot = MyAggregateRoot::class;
    
    /** @var string */
    protected $tableName = 'my_aggregate_root_domain_messages';

    /** @var array */
    protected $consumers = [

    ];

    /** @var array */
    protected $queuedConsumers = [

    ];
}

如果您不需要消费者或队列消费者,可以安全地删除这些变量。唯一必需的变量是 $aggregateRoot

当然,您也可以手动创建聚合根存储库。只需创建一个类,让它扩展 Spatie\LaravelEventSauce\AggregateRootRepository。接下来,在一个受保护的 $aggregateRoot 属性中放入您的聚合根的完全限定类名。最后,添加一个包含您要存储领域消息的表名的 $tableName 属性。

配置聚合根存储库

指定聚合根

$aggregateRoot 属性应包含一个聚合根的完全限定类名。一个有效的聚合根是任何实现 EventSauce\EventSourcing\AggregateRoot 的类。

添加消费者

消费者是接收所有事件并对它们执行某些操作的类,例如创建投影。$consumers 属性应是一个包含消费者类名的数组。一个有效的消费者是任何实现 EventSauce\EventSourcing\Consumer 的类。

添加队列消费者

除非您需要在同一请求中与您的命令或事件一起使用消费者结果,否则建议让消费者在队列中执行工作。《$queuedConsumers》属性应是一个包含消费者类名的数组。任何实现《EventSauce\EventSourcing\Consumer》的类都是有效的消费者。

如果有任何消息需要发送给这些消费者中的任何一个,默认情况下,包会通过《Spatie\LaravelEventSauce\QueuedMessageJob》来调度。

自定义传递消息到队列消费者的作业

默认情况下,使用《Spatie\LaravelEventSauce\QueuedMessageJob》来传递消息给队列消费者。您可以通过在《eventsauce》配置文件中将《queued_message_job》条目设置为自定义作业的类来自定义此作业。任何扩展《Spatie\LaravelEventSauce\QueuedMessageJob》的类都是有效的作业。

更改《queued_message_job》条目将更改所有聚合根存储库的默认作业。如果您想为特定的存储库更改作业类,请向该存储库添加一个《$queuedMessageJob》属性。

以下是一个示例

// ...

class MyAggregateRootRepository extends AggregateRootRepository
{
    // ...
    
    protected $queuedMessageJob = MyCustomJob::class;
}

您可以使用该自定义作业添加属性来控制超时、最大尝试次数和要使用的队列。有关如何配置作业的更多信息,请参阅《Laravel关于队列的文档》。

以下是一个自定义作业的示例。

use Spatie\LaravelEventSauce\QueuedMessageJob;

class MyCustomJob extends QueuedMessageJob
{
    /*
     * The name of the connection the job should be sent to.
     */
    public $connection = 'my-custom-connection';

    /*
     * The name of the queue the job should be sent to.
     */
    public $queue = 'my-custom-queue';

    /*
     * The number of times the job may be attempted.
     *
     * @var int
     */
    public $tries = 5;
    
    /*
     * The number of seconds the job can run before timing out.
     *
     * @var int
     */
    public $timeout = 120;
    
    /*
     * The number of seconds before the job should be made available.
     *
     * @var int|null
     */
    public $delay;
}

自定义存储消息的表名

您的聚合根存储库上的《$tableName》属性决定了消息的存储位置。只要您已创建一个具有以下列的具有该名称的表,您就可以将其更改为任何您想要的名称:

Schema::create('custom_table_name', function (Blueprint $table) {
    $table->increments('id');
    $table->string('event_id', 36);
    $table->string('event_type', 100);
    $table->string('aggregate_root_id', 36)->nullable()->index();
    $table->dateTime('recorded_at', 6)->index();
    $table->text('payload');
});

指定连接

Laravel支持多个数据库连接。默认情况下,聚合根将使用Laravel的默认连接。如果您想让所有聚合根使用相同的替代连接,请在《eventsauce》配置文件的《connection》属性中指定该连接名称。

如果您想让特定的存储库使用替代连接,只需在《$connection》属性中指定其名称即可。

// ...

class MyAggregateRootRepository extends AggregateRootRepository
{
    // ...
    
    protected $connection = 'connection-name';
}

代码生成

我们可以从YAML文件开始生成类型、事件和命令。您可以在《使用Yaml定义命令和事件》部分中阅读有关YAML文件内容以及生成的输出的更多信息。

要生成代码,请在《eventsauce》配置文件的《code_generation》部分中填写密钥,并执行此命令。

php artisan eventsauce:generate

测试

composer test

变更日志

请参阅《CHANGELOG》以获取有关最近更改的更多信息。

贡献

请参阅《CONTRIBUTING》以获取详细信息。

安全

如果您发现与安全相关的任何错误,请通过security@spatie.be发送邮件,而不是使用问题跟踪器。

Postcardware

您可以自由使用此包,但如果它进入您的生产环境,我们非常感谢您从您家乡寄给我们一张明信片,说明您正在使用我们的哪些包。

我们的地址是:Spatie,Kruikstraat 22,2018 Antwerp,比利时。

我们将在我们的公司网站上发布所有收到的明信片《在这里》。

鸣谢

此包的初始版本基于《LaravelEventSauce》的开发版本。

许可证

麻省理工学院许可证(MIT)。有关更多信息,请参阅许可证文件