PHPackages                             cv65kr/messenger - 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. [Framework](/categories/framework)
4. /
5. cv65kr/messenger

ActiveSymfony-bundle[Framework](/categories/framework)

cv65kr/messenger
================

CQRS + Event Sourcing for Symfony.

v0.1.0(6y ago)751[1 issues](https://github.com/cv65kr/messenger/issues)MITPHPPHP ^7.2CI failing

Since Feb 15Pushed 6y ago4 watchersCompare

[ Source](https://github.com/cv65kr/messenger)[ Packagist](https://packagist.org/packages/cv65kr/messenger)[ RSS](/packages/cv65kr-messenger/feed)WikiDiscussions master Synced today

READMEChangelog (1)Dependencies (8)Versions (2)Used By (0)

CQRS + Event Sourcing for Symfony
=================================

[](#cqrs--event-sourcing-for-symfony)

This is simple implementation CQRS + Event Sourcing for Symfony.

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

[](#installation)

```
composer require cv65kr/messenger
```

Activate in `config/bundles.php`:

```
Messenger\MessengerBundle::class => ['all' => true],
```

Update database (migration in future):

```
bin/console d:s:u --force --dump-sql
```

To activate async bus, open `config/packages/messenger.yaml` and paste:

```
framework:
    messenger:
        transports:
            events: "%env(MESSENGER_TRANSPORT_DSN)%"

        routing:
            'Messenger\Event\EventInterface': events
```

How to use
----------

[](#how-to-use)

The current example:

### Aggregate root

[](#aggregate-root)

```
class User extends AggregateRoot
{
    /** @var UuidInterface */
    private $uuid;

    /** @var Email */
    private $email;

    /** @var HashedPassword */
    private $hashedPassword;

    /** @var DateTime */
    private $createdAt;

    /** @var DateTime|null */
    private $updatedAt;

    public static function create(
        UuidInterface $uuid,
        Credentials $credentials,
        UniqueEmailSpecificationInterface $uniqueEmailSpecification
    ): self {
        $uniqueEmailSpecification->isUnique($credentials->email);

        $user = new self();

        $user->apply(new UserWasCreated($uuid, $credentials, DateTime::now()));

        return $user;
    }

    private function setEmail(Email $email): void
    {
        $this->email = $email;
    }

    private function setHashedPassword(HashedPassword $hashedPassword): void
    {
        $this->hashedPassword = $hashedPassword;
    }

    private function setCreatedAt(DateTime $createdAt): void
    {
        $this->createdAt = $createdAt;
    }

    private function setUpdatedAt(DateTime $updatedAt): void
    {
        $this->updatedAt = $updatedAt;
    }

    public function createdAt(): string
    {
        return $this->createdAt->toString();
    }

    public function updatedAt(): ?string
    {
        return isset($this->updatedAt) ? $this->updatedAt->toString() : null;
    }

    public function email(): string
    {
        return $this->email->toString();
    }

    public function uuid(): string
    {
        return $this->uuid->toString();
    }

    public function getAggregateRootId(): AggregateRootId
    {
        return AggregateRootId::fromUUID($this->uuid);
    }

    protected function applyUserWasCreated(UserWasCreated $event): void
    {
        $this->uuid = $event->uuid;

        $this->setEmail($event->credentials->email);
        $this->setHashedPassword($event->credentials->password);
        $this->setCreatedAt($event->createdAt);
    }

}
```

### Event Sourcing Repository

[](#event-sourcing-repository)

```
final class UserStore extends EventSourcingRepository implements UserRepositoryInterface
{
    public function store(User $user): void
    {
        $this->save($user);
    }

    public function get(UuidInterface $uuid): User
    {
        /** @var User $user */
        $user = $this->load(AggregateRootId::fromUUID($uuid));

        return $user;
    }

    public function getAggregateRoot(): string
    {
        return User::class;
    }
}
```

### Projection

[](#projection)

#### Read model

[](#read-model)

```
class UserView implements ReadModelInterface
{
    /** @var UuidInterface */
    private $uuid;

    /** @var Credentials */
    private $credentials;

    /** @var DateTime */
    private $createdAt;

    /** @var DateTime */
    private $updatedAt;

    public static function fromSerializable(EventInterface $event): self
    {
        return self::deserialize($event->serialize());
    }

    public static function deserialize(array $data): self
    {
        $instance = new self();

        $instance->uuid = Uuid::fromString($data['uuid']);
        $instance->credentials = new Credentials(
            Email::fromString($data['credentials']['email']),
            HashedPassword::fromHash($data['credentials']['password'] ?? '')
        );

        $instance->createdAt = DateTime::fromString($data['created_at']);
        $instance->updatedAt = isset($data['updated_at']) ? DateTime::fromString($data['updated_at']) : null;

        return $instance;
    }

    public function serialize(): array
    {
        return [
            'uuid' => $this->getId(),
            'credentials' => [
                'email' => (string) $this->credentials->email,
            ],
        ];
    }

    public function uuid(): UuidInterface
    {
        return $this->uuid;
    }

    public function email(): string
    {
        return (string) $this->credentials->email;
    }

    public function changeEmail(Email $email): void
    {
        $this->credentials->email = $email;
    }

    public function changeUpdatedAt(DateTime $updatedAt): void
    {
        $this->updatedAt = $updatedAt;
    }

    public function hashedPassword(): string
    {
        return (string) $this->credentials->password;
    }

    public function getId(): string
    {
        return $this->uuid->toString();
    }
}
```

#### Projector

[](#projector)

```
class UserProjectionFactory extends Projector
{
    /** @var MysqlUserReadModelRepository */
    private $repository;

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

    protected function applyUserWasCreated(UserWasCreated $userWasCreated): void
    {
        $userReadModel = UserView::fromSerializable($userWasCreated);

        $this->repository->add($userReadModel);
    }

    protected function applyUserEmailChanged(UserEmailChanged $emailChanged): void
    {
        /** @var UserView $userReadModel */
        $userReadModel = $this->repository->oneByUuid($emailChanged->uuid);

        $userReadModel->changeEmail($emailChanged->email);
        $userReadModel->changeUpdatedAt($emailChanged->updatedAt);

        $this->repository->apply();
    }
}
```

### Consume events from queue

[](#consume-events-from-queue)

```
class SendEventsToElasticConsumer implements EventHandlerInterface
{
    /** @var EventElasticRepository */
    private $eventElasticRepository;

    public function __construct(EventElasticRepository $eventElasticRepository)
    {
        $this->eventElasticRepository = $eventElasticRepository;
    }

    public function __invoke(EventInterface $event): void
    {
        $this->eventElasticRepository->store($event);
    }
}
```

###  Health Score

21

—

LowBetter than 18% of packages

Maintenance17

Infrequent updates — may be unmaintained

Popularity10

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

2330d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/9404962?v=4)[Kajetan](/maintainers/cv65kr)[@cv65kr](https://github.com/cv65kr)

---

Top Contributors

[![cv65kr](https://avatars.githubusercontent.com/u/9404962?v=4)](https://github.com/cv65kr "cv65kr (15 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/cv65kr-messenger/health.svg)

```
[![Health](https://phpackages.com/badges/cv65kr-messenger/health.svg)](https://phpackages.com/packages/cv65kr-messenger)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M738](/packages/sylius-sylius)[pimcore/pimcore

Content &amp; Product Management Framework (CMS/PIM/E-Commerce)

3.8k3.8M508](/packages/pimcore-pimcore)[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M386](/packages/easycorp-easyadmin-bundle)[shopware/platform

The Shopware e-commerce core

3.4k1.5M3](/packages/shopware-platform)[shopware/core

Shopware platform is the core for all Shopware ecommerce products.

585.6M574](/packages/shopware-core)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M203](/packages/sulu-sulu)

PHPackages © 2026

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