Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Event Sourcing Laravel Package

spatie/laravel-event-sourcing

Event sourcing toolkit for Laravel: build aggregates, projectors, and reactors to store state changes as events. Ideal for audit trails, decisions based on history, and future reporting needs. Includes docs, examples, and an optional course.

View on GitHub
Deep Wiki
Context7

title: Commands weight: 13

Our package supports a simple command bus implementation that's able to automatically map commands to aggregate roots. If you want to use dedicated command objects, this can be a useful feature in order to prevent much boilerplate for writing command handlers. It's also possible to manually create command handlers if you want to.

A command looks like this:

namespace Spatie\Shop\Cart\Commands;

use Spatie\Shop\Support\EventSourcing\Attributes\AggregateUuid;
use Spatie\Shop\Support\EventSourcing\Attributes\HandledBy;

#[HandledBy(CartAggregateRoot::class)]
class AddCartItem
{
    public function __construct(
        #[AggregateUuid] public string $cartUuid,
        public string $cartItemUuid,
        public Product $product,
        public int $amount,
    ) {
    }
}

The #[HandledBy] attribute takes any invokable class. If you use an aggregate root class, the #[AggregateUuid] property is also required in order to map a command to an aggregate root.

If a command is handled by an aggregate root, you can simply add a method on that aggregate root which takes the command as an argument, and the rest will be handled for you:

class CartAggregateRoot extends AggregateRoot
{
    // …

    public function addItem(
        AddCartItem $addCartItem
    ): self {
        // …
    }
}

Also note that these commands can be mapped to aggregate partials, this is especially useful when you don't want to provide a manual mapping of public methods between the aggregate root and its partials.

class CartItems extends AggregatePartial
{
    // …

    public function addItem(
        AddCartItem $addCartItem
    ): self {
        // …
    }
}

Finally, a command is dispatched on the CommandBus, which is registered in Laravel's container, so you can inject is wherever needed:

class CartController
{
    public function addCartItem(
        Request $request,
        CommandBus $commandBus
    ): void {
        $commandBus->dispatch(new AddCartItem(
            cartUuid: /* … */,
            cartItemUuid: /* … */,
            product: /* … */,
            amount: /* … */,
        ));
    }
}

Want to know more?

Commands can be a very useful tool in complex applications. Our course, Event Sourcing in Laravel covers them in depth:

    1. The Command Bus
    1. CQRS
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport