An open API service indexing awesome lists of open source software.

https://github.com/nixilla/cqrs-bundle

Symfony Bundle that integrates Prooph CQRS/ES library
https://github.com/nixilla/cqrs-bundle

cqrs event-sourcing prooph symfony-bundle

Last synced: 6 months ago
JSON representation

Symfony Bundle that integrates Prooph CQRS/ES library

Awesome Lists containing this project

README

        

# CQRS/ES Bundle for Symfony which integrates Prooph library

This Symfony Bundle wires Prooph CQRS/ES library into Symfony project.

[![Build Status](https://travis-ci.org/nixilla/cqrs-bundle.svg?branch=master)](https://travis-ci.org/nixilla/cqrs-bundle)
[![Coverage Status](https://coveralls.io/repos/github/nixilla/cqrs-bundle/badge.svg)](https://coveralls.io/github/nixilla/cqrs-bundle)

## Installation

Install with composer:

```bash
composer require nixilla/cqrs-bundle
```

Add budle to AppKernel:

```php
add('emailAddress', EmailType::class, [
'constraints' => [ new NotBlank(), new Email() ]
])
;
}
}
```

```php
form->submit(json_decode($request->getContent(), true));

if($this->form->isValid())
{
$this->commandBus->dispatch(new CreateContact($this->form->getData()));
return new Response('', 201);
}

return new Response($this->form->getErrors(true)->__toString(), 422);
}
}
```

The commandBus service is provided by this bundle, but CreateContact command is something we will created now.
This is the first CQRS artifact.

```php
init();
$this->setPayload($payload);
}

public function payload() { return $this->payload; }

protected function setPayload(array $payload) { $this->payload = $payload; }
}
```

Now if configure routing like this:

```yml
# src/AppBundle/Resources/config/routing.yml

contact_create:
path: /contact
defaults: { _controller: controller.contact.create:createAction }
methods: [ POST ]
```

then you should be able to call it with curl like this:

```bash
curl -v \
-H "Content-Type: application/json" \
-X POST \
--data '{"emailAddress":"[email protected]"}' \
http://localhost/contact
```
When you actually run this command now, you'll get exception `Message dispatch failed during locate-handler phase. Error: You have requested a non-existent service "handler.create_contact".`

The `handler.create_contact` is the service which we will create next. The only purpose for this service is to handle
`CreateContact` command. In other words, each command has only one command handler, and each command handler can only
handle one command.

```php
repository->add(Contact::fromPayload($command->payload()));
}
}
```

This handler require 2 additional CQRS artifacts.

First one is ContactRepository which usually has 2 methods: `get` and `add`.

```php
repository->addAggregateRoot($contact); }

public function get($id) { return $this->repository->getAggregateRoot($id); }
}
```

Second one is event, which is recorded in data store. All events are in past tense. Good thing is that you don't
have to write any code - just extend base class.

```php
payload();
$message = sprintf("New Newsletter subscription, email address '%s'", $payload['emailAddress']);
$this->notifier->notify('red', $message, 'text', true);
}
}
```

and to make it work, you need to let know Symfony how to inject it.

```yaml

# src/AppBundle/Resources/config/services.yml

services:

listener.contact_created:
class: AppBundle\Cqrs\Listeners\MarketingNotificationListener
arguments: [ "@hipchat.notifier" ]
tags:
- { name: cqrs.event.listener, event: Newsletter\Domain\Event\ContactCreated }

```

A single event can have many event listeners and many projectors. So in order to configure listener, you need
to tag service with `{ name: cqrs.event.listener, event: Newsletter\Domain\Event\ContactCreated }`
This will add listener to array of listeners for given event class, and when that even occurs, all listeners will be
executed.

A sample projector may look like this:

```php
payload();
$this->campaignMonitor->subscribe($payload['emailAddress'], $listId = 'my list id');
}
}
```

wiring is similar to what you see in the listeners section above, but it is important to tag it with `cqrs.event.projector`.

```yaml

# src/AppBundle/Resources/config/services.yml

services:

projector.campaign_monitor.contact_created:
class: AppBundle\Cqrs\Projectors\CampaignMonitorContactCreatedProjector
arguments: [ "@campaign.monitor" ]
tags:
- { name: cqrs.event.projector, event: Newsletter\Domain\Event\ContactCreated }

```