Skip to content
This repository has been archived by the owner on Feb 21, 2022. It is now read-only.

Commit

Permalink
Merge branch 'GH-28'
Browse files Browse the repository at this point in the history
  • Loading branch information
beberlei committed Feb 26, 2013
2 parents 1d7fe6b + 6f07bd4 commit 5210bfc
Show file tree
Hide file tree
Showing 30 changed files with 202 additions and 93 deletions.
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# LiteCQRS for PHP

Small convention based CQRS library for PHP (loosely based on [LiteCQRS for
Small naming-convention based CQRS library for PHP (loosely based on [LiteCQRS for
C#](https://github.com/danielwertheim/LiteCQRS)) that relies on the Message Bus,
Command, Event and Domain Event patterns.

Expand All @@ -25,29 +25,34 @@ and its implementation ``LiteCQRS\AggregateRoot``.
LiteCQRS uses the command pattern and a central message bus service that
handles commands and finds their corresponding handler to execute them.

## Changes

### From 1.0 to 1.1

* Extending ``LiteCQRS\Command`` and ``LiteCQRS\DomainEvent`` is NOT required anymore.
In fact you can use any class as command or event. The naming conventions alone
make sure command handlers and event listeners are detected.

## Conventions

* All public methods of a command handler class are mapped to Commands "Command
Class Shortname" => "MethodName"
Class Shortname" => "MethodName" when the method and command class shortname match.
Implementing an interface for the commands is NOT required (since 1.1)
* Domain Events are applied to Event Handlers "Event Class Shortname" =>
"onEventClassShortname". Only if this matches is an event listener registered.
* Domain Events are applied on Entities/Aggregate Roots "Event Class Shortname"
=> "applyEventClassShortname"
* Domain Events are applied to Event Handlers "Event Class Shortname" =>
"onEventClassShortname"
* You can use the ``DomainObjectChanged`` Event to avoid creating lots of event
classes. You can dynamically set the event name on it and exchange it with a
real event implementation when it becomes necessary.
* Otherwise you can extend the ``DefaultDomainEvent`` which has a constructor
* You can optionally extend the ``DefaultDomainEvent`` which has a constructor
that maps its array input to properties and throws an exception if an unknown
property is passed.
* There is also a ``DefaultCommand`` with the same semantics as
``DefaultDomainEvent``
``DefaultDomainEvent``. Extending this is not required.

Examples:

* ``HelloWorld\GreetingCommand`` maps to the ``greeting($command)`` method on the registered handler.
* ``HelloWorld\GreetingCommand`` maps to the ``greeting(GreetingCommand $command)`` method on the registered handler.
* ``HelloWorld\GreetedEvent`` is passed to all event handlers that have a method ``onGreeted(GreetedEvent $event)``.
* ``HelloWorld\GreetedEvent`` is delegated to ``applyGreeted($event)`` when created on the aggregate root
* ``HelloWorld\GreetedEvent`` is passed to all event handlers that have a method ``onGreeted($event)``.
* ``new DomainObjectChanged("Greeted", array("foo" => "bar"))`` is mapped to the "Greeted" event.

## Installation & Requirements

Expand Down Expand Up @@ -180,7 +185,6 @@ If you want to log all commands:
```php
<?php
use LiteCQRS\Bus\MessageHandlerInterface;
use LiteCQRS\Bus\MessageInterface;

class CommandLogger implements MessageHandlerInterface
{
Expand All @@ -191,7 +195,7 @@ class CommandLogger implements MessageHandlerInterface
$this->next = $next;
}

public function handle(MessageInterface $command)
public function handle($command)
{
syslog(LOG_INFO, "Executing: " . get_class($command));
$this->next->handle($command);
Expand Down
6 changes: 3 additions & 3 deletions src/LiteCQRS/Bus/AbstractEventMessageBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ protected function sort($events)
return $events;
}

protected function handle(DomainEvent $event)
protected function handle($event)
{
$eventName = strtolower($event->getEventName());
$eventName = new EventName($event);
$services = $this->getHandlers($eventName);

foreach ($services as $service) {
Expand All @@ -91,7 +91,7 @@ protected function invokeEventHandler($service, $event)
}
}

abstract protected function getHandlers($eventName);
abstract protected function getHandlers(EventName $eventName);
}


4 changes: 1 addition & 3 deletions src/LiteCQRS/Bus/CommandBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@

namespace LiteCQRS\Bus;

use LiteCQRS\Command;

/**
* Accept and process commands by passing them along to a matching command handler.
*/
interface CommandBus
{
public function handle(Command $command);
public function handle($command);
}

7 changes: 3 additions & 4 deletions src/LiteCQRS/Bus/CommandInvocationHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace LiteCQRS\Bus;

use LiteCQRS\Command;

class CommandInvocationHandler implements MessageHandlerInterface
{
private $service;
Expand All @@ -13,9 +11,9 @@ public function __construct($service)
$this->service = $service;
}

public function handle(MessageInterface $command)
public function handle($command)
{
if (!($command instanceof Command)) {
if ( ! is_object($command)) {
throw new \RuntimeException("No command given to CommandInvocationHandler.");
}

Expand All @@ -31,6 +29,7 @@ public function handle(MessageInterface $command)
public function getHandlerMethodName($command)
{
$parts = explode("\\", get_class($command));

return str_replace("Command", "", lcfirst(end($parts)));
}
}
Expand Down
11 changes: 4 additions & 7 deletions src/LiteCQRS/Bus/EventInvocationHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace LiteCQRS\Bus;

use LiteCQRS\DomainEvent;

class EventInvocationHandler implements MessageHandlerInterface
{
private $service;
Expand All @@ -13,12 +11,11 @@ public function __construct($service)
$this->service = $service;
}

public function handle(MessageInterface $event)
public function handle($event)
{
if (!($event instanceof DomainEvent)) {
throw new \RuntimeException("No DomainEvent instance passed to EventInvocationHandler");
}
$methodName = "on" . $event->getEventName();
$eventName = new EventName($event);
$methodName = "on" . $eventName;

$this->service->$methodName($event);
}
}
Expand Down
27 changes: 10 additions & 17 deletions src/LiteCQRS/Bus/EventMessageHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@ class EventMessageHandler implements MessageHandlerInterface
{
private $messageBus;
private $next;
private $identityMap;
private $queue;
private $eventStore;

public function __construct(MessageHandlerInterface $next, EventMessageBus $messageBus, IdentityMapInterface $identityMap = null, EventStoreInterface $eventStore = null)
public function __construct(MessageHandlerInterface $next, EventMessageBus $messageBus, EventQueue $queue = null, EventStoreInterface $eventStore = null)
{
$this->next = $next;
$this->messageBus = $messageBus;
$this->identityMap = $identityMap;
$this->queue = $queue;
$this->eventStore = $eventStore;
}

public function handle(MessageInterface $command)
public function handle($command)
{
try {
$this->next->handle($command);
Expand All @@ -34,23 +34,16 @@ public function handle(MessageInterface $command)

protected function passEventsToStore()
{
if (!$this->identityMap) {
if (!$this->queue) {
return;
}

foreach ($this->identityMap->all() as $aggregateRoot) {
$id = $this->identityMap->getAggregateId($aggregateRoot);
foreach ($aggregateRoot->dequeueAppliedEvents() as $event) {
$header = $event->getMessageHeader();
$header->aggregateType = get_class($aggregateRoot);
$header->aggregateId = $id;
$header->setAggregate(null);

if ($this->eventStore) {
$this->eventStore->store($event);
}
$this->messageBus->publish($event);
foreach ($this->queue->dequeueAllEvents() as $event) {
if ($this->eventStore) {
$this->eventStore->store($event);
}

$this->messageBus->publish($event);
}
}
}
Expand Down
9 changes: 4 additions & 5 deletions src/LiteCQRS/Bus/EventMessageHandlerFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@

namespace LiteCQRS\Bus;

use LiteCQRS\Command;
use LiteCQRS\EventStore\EventStoreInterface;

class EventMessageHandlerFactory
{
private $messageBus;
private $identityMap;
private $queue;
private $eventStore;

public function __construct(EventMessageBus $messageBus, IdentityMapInterface $identityMap = null, EventStoreInterface $eventStore = null)
public function __construct(EventMessageBus $messageBus, EventQueue $queue = null, EventStoreInterface $eventStore = null)
{
$this->messageBus = $messageBus;
$this->identityMap = $identityMap;
$this->queue = $queue;
$this->eventStore = $eventStore;
}

public function __invoke($handler)
{
return new EventMessageHandler($handler, $this->messageBus, $this->identityMap, $this->eventStore);
return new EventMessageHandler($handler, $this->messageBus, $this->queue, $this->eventStore);
}
}

45 changes: 45 additions & 0 deletions src/LiteCQRS/Bus/EventName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace LiteCQRS\Bus;

use LiteCQRS\DomainEvent;

class EventName
{
private $event;
private $name;

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

public function __toString()
{
if ($this->name === null) {
$this->name = $this->parseName();
}

return $this->name;
}

private function parseName()
{
if ($this->event instanceof DomainEvent) {
return $this->event->getEventName();
}

$class = get_class($this->event);

if (substr($class, -5) === "Event") {
$class = substr($class, 0, -5);
}

if (strpos($class, "\\") === false) {
return $class;
}

$parts = explode("\\", $class);
return end($parts);
}
}
16 changes: 16 additions & 0 deletions src/LiteCQRS/Bus/EventQueue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace LiteCQRS\Bus;

/**
* Allows access to all events that commands have triggered.
*/
interface EventQueue
{
/**
* Dequeue all events from the queue and return them in order.
*
* @return array<object>
*/
public function dequeueAllEvents();
}
39 changes: 39 additions & 0 deletions src/LiteCQRS/Bus/IdentityMap/EventProviderQueue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace LiteCQRS\Bus\IdentityMap;

use LiteCQRS\Bus\EventQueue;

/**
* Returns all events from {@see EventProviderInterface} instances
* that are saved in the identity map.
*/
class EventProviderQueue implements EventQueue
{
private $identityMap;

public function __construct(IdentityMapInterface $identityMap)
{
$this->identityMap = $identityMap;
}

public function dequeueAllEvents()
{
$dequeueEvents = array();

foreach ($this->identityMap->all() as $aggregateRoot) {
$id = $this->identityMap->getAggregateId($aggregateRoot);

foreach ($aggregateRoot->dequeueAppliedEvents() as $event) {
$header = $event->getMessageHeader();
$header->aggregateType = get_class($aggregateRoot);
$header->aggregateId = $id;
$header->setAggregate(null);

$dequeueEvents[] = $event;
}
}

return $dequeueEvents;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace LiteCQRS\Bus;
namespace LiteCQRS\Bus\IdentityMap;

use LiteCQRS\EventProviderInterface;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace LiteCQRS\Bus;
namespace LiteCQRS\Bus\IdentityMap;

use LiteCQRS\EventProviderInterface;

Expand Down
4 changes: 3 additions & 1 deletion src/LiteCQRS/Bus/InMemoryEventMessageBus.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public function register($handler)
}
}

protected function getHandlers($eventName)
protected function getHandlers(EventName $eventName)
{
$eventName = strtolower($eventName);

if (!isset($this->handlers[$eventName])) {
return array();
}
Expand Down
2 changes: 1 addition & 1 deletion src/LiteCQRS/Bus/MessageHandlerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

interface MessageHandlerInterface
{
public function handle(MessageInterface $message);
public function handle($message);
}

Loading

0 comments on commit 5210bfc

Please sign in to comment.