PHPackages                             spatie/laravel-eventsauce - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. spatie/laravel-eventsauce

ActiveLibrary

spatie/laravel-eventsauce
=========================

Use EventSauce in Laravel apps

2.1.0(5y ago)12115.9k↓48.8%151MITPHPPHP ^8.0|^7.4CI failing

Since Jan 20Pushed 3mo ago5 watchersCompare

[ Source](https://github.com/spatie/laravel-eventsauce)[ Packagist](https://packagist.org/packages/spatie/laravel-eventsauce)[ Docs](https://github.com/spatie/laravel-eventsauce)[ GitHub Sponsors](https://github.com/spatie)[ RSS](/packages/spatie-laravel-eventsauce/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (8)Dependencies (10)Versions (10)Used By (1)

Use EventSauce in Laravel apps
==============================

[](#use-eventsauce-in-laravel-apps)

[![Latest Version on Packagist](https://camo.githubusercontent.com/34fcec17ccac6ef442a592f9ac413e25e1f6234756b7394e5039ad65a9e6d6a6/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7370617469652f6c61726176656c2d6576656e7473617563652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-eventsauce)[![Tests](https://github.com/spatie/laravel-eventsauce/workflows/run-tests/badge.svg)](https://github.com/spatie/laravel-eventsauce/workflows/run-tests/badge.svg)[![Total Downloads](https://camo.githubusercontent.com/2e554ecbebfc1c503a34ae1e9e0444493dffe9da6e924a499af30e07c97fe9ee/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7370617469652f6c61726176656c2d6576656e7473617563652e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spatie/laravel-eventsauce)

[EventSauce](https://eventsauce.io/) is an easy way to introduce event sourcing into PHP projects. This package allows EventSauce to make use of Laravel's migrations, models and jobs. It can also help with generating code for commands and events. If you want to use EventSauce in a Laravel app, this package is the way to go!

Before using laravel-eventsauce you should already know how to work with EventSauce.

Here's a quick example of how to create a new aggregate root and matching repository. Let's run this command:

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

The `App\MyDomain\MyAggregateRoot` and `App\MyDomain\MyAggregateRootRepository` classes will have been created. A migration to create `my_aggregate_root_domain_messages` will have been added to your application too. This is how `MyAggregateRootRepository` looks like:

```
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 = [

    ];
}
```

You can put classnames of consumers in the `$consumers` array. Consumers in the `$queuedConsumers` array will called and be passed their messages using a queued job.

The `MyAggregateRootRepository` can be injected and used in any class. In this example we assume you've manually created a `performMySpecialCommand` method on `MyAggregateRoot`:

```
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);
        }
    }
}
```

Support us
----------

[](#support-us)

[![](https://camo.githubusercontent.com/f4943259d469b66215723e2577b5e20aec2ecd06aae32bae210edf435ccc260d/68747470733a2f2f6769746875622d6164732e73332e65752d63656e7472616c2d312e616d617a6f6e6177732e636f6d2f6c61726176656c2d6576656e7473617563652e6a70673f743d31)](https://spatie.be/github-ad-click/laravel-eventsauce)

We invest a lot of resources into creating [best in class open source packages](https://spatie.be/open-source). You can support us by [buying one of our paid products](https://spatie.be/open-source/support-us).

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on [our contact page](https://spatie.be/about-us). We publish all received postcards on [our virtual postcard wall](https://spatie.be/open-source/postcards).

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require spatie/laravel-eventsauce
```

Next you must publish the `eventsauce` config file.

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

This is the contents of the file that will be publish to `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,
];
```

Usage
-----

[](#usage)

### Generating an aggregate root and repository

[](#generating-an-aggregate-root-and-repository)

An aggregate root and matching repository can be generated used this command

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

This command will create `App\MyDomain\MyAggregateRoot` and `App\MyDomain\MyAggregateRootRepository`.

This is how `MyAggregateRootRepository` looks like:

```
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 = [

    ];
}
```

If you repository doesn't need consumers or queued consumers, you can safely remove those variables. The only required variable is `$aggregateRoot`.

Of course you can also manually create an aggregate root repository. Just create a class, let it extend`Spatie\LaravelEventSauce\AggregateRootRepository`. Next, put the fully qualified classname of your aggregate root in a protected `$aggregateRoot` property. Finally add a `$tableName` property containing the name of the table where you want to store domain messages.

### Configuring the aggregate root repository

[](#configuring-the-aggregate-root-repository)

#### Specifying the aggregate root

[](#specifying-the-aggregate-root)

The `$aggregateRoot` property should contain the fully qualied class name of an aggregate root. A valid aggregate root is any class that implements `EventSauce\EventSourcing\AggregateRoot`

#### Adding consumers

[](#adding-consumers)

Consumers are classes that receive all events and do something with them, for example creation a projection. The `$consumers` property should be an array that contains class names of consumers. A valid consumer is any class that implements `EventSauce\EventSourcing\Consumer`.

#### Adding queued consumers

[](#adding-queued-consumers)

Unless you need the result of a consumer in the same request as your command or event is fired, it's recommanded to let a consumer to perform it's work on a queue. The `$queuedConsumers` property should be an array that contains class names of consumers. A valid consumer is any class that implements `EventSauce\EventSourcing\Consumer`.

If there are any message that needs to be sent to any of these consumers, the package will dispatch a `Spatie\LaravelEventSauce\QueuedMessageJob` by default.

#### Customizing the job that passes messages to queued consumers

[](#customizing-the-job-that-passes-messages-to-queued-consumers)

By default `Spatie\LaravelEventSauce\QueuedMessageJob` is used to pass messages to queued consumers. You can customized this job by setting the `queued_message_job` entry in the `eventsauce` config file to the class of your custom job. A valid job is any class that extends `Spatie\LaravelEventSauce\QueuedMessageJob`.

Changing the `queued_message_job` entry will change the default job of all aggregate root repositories. If you want to change the job class for a specific repository add a `$queuedMessageJob` property to that repository.

Here is an example:

```
// ...

class MyAggregateRootRepository extends AggregateRootRepository
{
    // ...

    protected $queuedMessageJob = MyCustomJob::class;
}
```

You can use that custom job to add properties to control the timeout, max attempts and the queue to be used. You can read more on how to configure a job in the [Laravel docs on queueing](https://laravel.com/docs/master/queues).

Here's an example of a custom job.

```
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;
}
```

### Customizing the table name where messages are stored

[](#customizing-the-table-name-where-messages-are-stored)

The `$tableName` property on your aggregate root repository determines where messages are being stored. You can change this to any name you want as long as you've created a a table with that name that has the following columns:

```
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');
});
```

### Specifying a connection

[](#specifying-a-connection)

Laravel has support for multiple database connections. By default the aggregate root will use Laravel's default connection. If you want all your aggregate roots to use a the same alternative connection then specify that connection name in the `connection` property of the `eventsauce` config file.

If you want let a specific repository use an alternative connection, you can just specify it's name in the `$connection` property

```
// ...

class MyAggregateRootRepository extends AggregateRootRepository
{
    // ...

    protected $connection = 'connection-name';
}
```

### Code generation

[](#code-generation)

We can generate types, events and commands from you starting from a yaml file. You can read more on the contents of the yaml file and the generated output in the "[Defining command and events using Yaml](https://eventsauce.io/docs/getting-started/create-events-and-commands/)" section of the EventSauce docs.

To generate code, fill in the keys in the `code_generation` parts of the `eventsauce` config file and execute this command.

```
php artisan eventsauce:generate

```

### Testing

[](#testing)

```
composer test
```

### Changelog

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](https://github.com/spatie/.github/blob/main/CONTRIBUTING.md) for details.

### Security

[](#security)

If you've found a bug regarding security please mail  instead of using the issue tracker.

Postcardware
------------

[](#postcardware)

You're free to use this package, but if it makes it to your production environment we highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using.

Our address is: Spatie, Kruikstraat 22, 2018 Antwerp, Belgium.

We publish all received postcards [on our company website](https://spatie.be/en/opensource/postcards).

Credits
-------

[](#credits)

- [Freek Van der Herten](https://github.com/freekmurze)

The initial version of this package was based upon a development version of [LaravelEventSauce](https://github.com/EventSaucePHP/LaravelEventSauce).

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

51

—

FairBetter than 96% of packages

Maintenance54

Moderate activity, may be stable

Popularity42

Moderate usage in the ecosystem

Community22

Small or concentrated contributor base

Maturity71

Established project with proven stability

 Bus Factor1

Top contributor holds 86% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~85 days

Recently: every ~159 days

Total

9

Last Release

1993d ago

Major Versions

0.1.0 → 1.0.02019-02-11

1.1.0 → v2.x-dev2020-06-26

PHP version history (4 changes)0.0.1PHP ^7.2

1.0.0PHP ^7.3

2.0.0PHP ^7.4

2.1.0PHP ^8.0|^7.4

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7535935?v=4)[Spatie](/maintainers/spatie)[@spatie](https://github.com/spatie)

---

Top Contributors

[![freekmurze](https://avatars.githubusercontent.com/u/483853?v=4)](https://github.com/freekmurze "freekmurze (117 commits)")[![AdrianMrn](https://avatars.githubusercontent.com/u/12762044?v=4)](https://github.com/AdrianMrn "AdrianMrn (8 commits)")[![leMaur](https://avatars.githubusercontent.com/u/2118799?v=4)](https://github.com/leMaur "leMaur (5 commits)")[![peter279k](https://avatars.githubusercontent.com/u/9021747?v=4)](https://github.com/peter279k "peter279k (2 commits)")[![AlexVanderbist](https://avatars.githubusercontent.com/u/6287961?v=4)](https://github.com/AlexVanderbist "AlexVanderbist (2 commits)")[![kduma](https://avatars.githubusercontent.com/u/1062582?v=4)](https://github.com/kduma "kduma (1 commits)")[![timopruesse](https://avatars.githubusercontent.com/u/13467720?v=4)](https://github.com/timopruesse "timopruesse (1 commits)")

---

Tags

event-sourcingeventsaucelaravelspatieeventsevent sourcingEventSaucelaravel-eventsauce

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/spatie-laravel-eventsauce/health.svg)

```
[![Health](https://phpackages.com/badges/spatie-laravel-eventsauce/health.svg)](https://phpackages.com/packages/spatie-laravel-eventsauce)
```

###  Alternatives

[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.1k84.2M225](/packages/laravel-horizon)[spatie/laravel-backup

A Laravel package to backup your application

6.0k21.8M191](/packages/spatie-laravel-backup)[sassnowski/venture

A package to manage complex workflows built on top of Laravel's queue.

825254.5k1](/packages/sassnowski-venture)[roots/acorn

Framework for Roots WordPress projects built with Laravel components.

9682.1M97](/packages/roots-acorn)[spatie/laravel-responsecache

Speed up a Laravel application by caching the entire response

2.8k8.2M51](/packages/spatie-laravel-responsecache)[tightenco/jigsaw

Simple static sites with Laravel's Blade.

2.2k438.5k29](/packages/tightenco-jigsaw)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
