Laravel Event Sourcing の新しいメジャーバージョン
(CJP) 今日、spatie/laravel-event-sourcing の新しいバージョンをリリースしました。バージョン 5 は、パッケージの開始以来おそらく最大のリリースの 1 つです。数か月間作業を行い、すでに独自の環境で広範囲にテストしてきました。プロジェクト。
多くの新機能は Axon にインスパイアされています。
Java の世界で人気のあるイベント ソーシング フレームワークであり、開発プロセス中に何人かの人々が参加しました。
この投稿では、すべての重要な変更について説明しますが、最初に、過去数か月にわたって Spatie で構築されたイベント ソーシングに関するコースについて言及したいと思います。 イベント ソース プロジェクトに取り組んでいる場合、またはプロジェクトを開始しようと考えている場合、このコースは非常に役立ちます。 https://event-sourcing-laravel.com/でチェックしてください!
# 一貫したイベント処理
以前のバージョンのパッケージを使用したことがある場合は、クラス間でイベント ハンドラーを登録する方法に苦労したかもしれません。 集約ルートはあなたが書く必要がありました applyEventName プロジェクターとリアクターには明示的なイベント マッピングがありました。
どのクラスを作成していても、同じ方法でイベント ハンドラーを登録します。つまり、イベントの種類を調べます。 構成や命名規則はもう必要ありません。
class CartAggregateRoot extends AggregateRoot
public function onCartAdded(CartAdded $event): void
class CartProjector extends Projector
public function onCartAdded(CartAdded $event): void
# イベントクエリ
イベント クエリは、データベース プロジェクションを構築せずにイベント ストリームを簡単にクエリできる新機能です。 それらは、呼び出すたびに再構築されるメモリ内プロジェクションと考えることができます。
実際の例を次に示します。
class EarningsForProductAndPeriod extends EventQuery
private int $totalPrice = 0;
public function __construct(
private Period $period,
private Collection $products
)
EloquentStoredEvent::query()
->whereEvent(OrderCreated::class)
->whereDate(‘created_at’, ‘>=’, $this->period->getStart())
->whereDate(‘created_at’, ‘period->getEnd())
->cursor()
->each(
fn (EloquentStoredEvent $event) => $this->apply($event)
);
protected function applyOrderCreated(OrderCreated $orderCreated): void
$orderLines = collect($orderCreated->orderData->orderLineData);
$totalPriceForOrder = $orderLines
->filter(function (OrderLineData $orderLineData)
return $this->products->first(
fn(Product $product) => $orderLineData->productEquals($product)
) !== null;
)
->sum(
fn(OrderLineData $orderLineData) => $orderLineData->totalPriceIncludingVat
);
$this->totalPrice += $totalPriceForOrder;
これらの例は Event Sourcing in Laravel book からのものであることに注意してください。
# パーシャルの集約
集約パーシャルを使用すると、大きな集約ルートを個別のクラスに分割しながら、すべてを同じ集約内に保持できます。 パーシャルは、集約ルートと同様にイベントを記録および適用でき、パーシャルと関連する集約ルートの間で状態を共有できます。
以下は、ショッピング カート内のアイテム管理に関連するすべてを処理する集約パーシャルの例です。
class CartItems extends AggregatePartial
public function addItem(
string $cartItemUuid,
Product $product,
int $amount
): self
$this->recordThat(new CartItemAdded(
cartItemUuid: $cartItemUuid,
productUuid: $product->uuid,
amount: $amount,
));
return $this;
protected function applyCartItemAdded(
CartItemAdded $cartItemAdded
): void
$this->cartItems[$cartItemAdded->cartItemUuid] = null;
そして、これはカート集約ルートがそれを使用する方法です:
class CartAggregateRoot extends AggregateRoot
{
protected CartItems $cartItems;
public function __construct()
$this->cartItems = new CartItems($this);
public function addItem(
string $cartItemUuid,
Product $product,
int $amount
): self
if (! $this->state->changesAllowed())
throw new CartCannotBeChanged();
$this->cartItems->addItem($cartItemUuid, $product, $amount);
return $this;
集約パーシャルには、集約ルートと同じテスト機能が付属しており、集約関連のコードを保守可能に保つための便利な方法です。
# コマンドバス
コマンドを集約ルートのハンドラーに自動的にマップできるコマンド バスを追加しました。
namespace Spatie\Shop\Cart\Commands;
use Spatie\Shop\Support\EventSourcing\Attributes\AggregateUuid;
use Spatie\Shop\Support\EventSourcing\Attributes\HandledBy;
use Spatie\Shop\Support\EventSourcing\Commands\Command;
class AddCartItem implements Command
public function __construct(
public string $cartUuid,
public string $cartItemUuid,
public Product $product,
public int $amount,
)
このコマンドがディスパッチされるたびに、関連する集約ルートによって自動的に取得および処理されます。 集約パーシャルでも機能します。
class CartItems extends AggregatePartial
public function addItem(AddCartItem $addCartItem): self
public function removeItem(RemoveCartItem $removeCartItem): self
これらの新機能に加えて、全体的にいくつかの生活の質の変化もあります。
全体として、私はこの新しいリリースに非常に興奮しています. すべての新機能は実際のプロジェクトでも使用されているため、複雑なアプリケーションでそれらがどれほど役立つかを経験から知っています. もちろん、ブログ投稿では、この新しいバージョンの背後にあるすべての詳細と思考プロセスについて説明することはできません。したがって、これらすべての機能などに関する詳細な知識が必要な場合は、必ず本を読んでください。
tpyoに気づきましたか? PR を送信して修正することができます。 このブログの最新情報を知りたい場合は、私をフォローしてください。 ツイッター または私のニュースレターを購読してください: