Skip to content
This repository has been archived by the owner on Sep 20, 2019. It is now read-only.

Commit

Permalink
Merge pull request #178 from spatie/event-map
Browse files Browse the repository at this point in the history
Add event_class_map for event class aliases
  • Loading branch information
freekmurze committed Jul 18, 2019
2 parents 2c05997 + 5716b6a commit af6fa8b
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Expand Up @@ -2,6 +2,9 @@

All notable changes to `laravel-event-projector` will be documented in this file

## x.x.x - 2019-xx-xx
- Added `event_class_map` to alias your event classes which allows for refactoring after events have been fired

## 2.6.3 - 2019-06-14

- fix warnings in console commands
Expand Down
7 changes: 7 additions & 0 deletions config/event-projector.php
Expand Up @@ -55,6 +55,13 @@
*/
'stored_event_job' => \Spatie\EventProjector\HandleStoredEventJob::class,

/*
* Similar to Relation::morphMap() you can define which alias responds to which
* event class. This allows you to change the namespace or classnames
* of your events but still handle older events correctly.
*/
'event_class_map' => [],

/*
* This class is responsible for serializing events. By default an event will be serialized
* and stored as json. You can customize the class name. A valid serializer
Expand Down
21 changes: 21 additions & 0 deletions docs/advanced-usage/using-aliases-for-stored-event-classes.md
@@ -0,0 +1,21 @@
---
title: Using aliases for stored event classes
weight: 8
---

By default we store the `Event`'s FQCN in the database when storing the events. This prevents you from changing the name or the namespace of your event classes.

To get around this you can define event class aliases in the `event-projector.php` config file:

```php
/*
* Similar to Relation::morphMap() you can define which alias responds to which
* event class. This allows you to change the namespace or classnames
* of your events but still handle older events correctly.
*/
'event_class_map' => [
'money_added' => MoneyAddedEvent::class,
],
```

With this configuration, instead of saving `\App\Events\MoneyAddedEvent` in the database, we just store `money_added`, now you can change the event classname and namespace. Just make sure to also change the mapping!
7 changes: 7 additions & 0 deletions docs/installation-setup.md
Expand Up @@ -79,6 +79,13 @@ return [
* it should extend \Spatie\EventProjector\HandleDomainEventJob.
*/
'stored_event_job' => \Spatie\EventProjector\HandleStoredEventJob::class,

/*
* Similar to Relation::morphMap() you can define which alias responds to which
* event class. This allows you to change the namespace or classnames
* of your events but still handle older events correctly.
*/
'event_class_map' => [],

/*
* This class is responsible for serializing events. By default an event will be serialized
Expand Down
24 changes: 23 additions & 1 deletion src/Models/StoredEvent.php
Expand Up @@ -4,6 +4,7 @@

use Exception;
use Carbon\Carbon;
use Illuminate\Support\Arr;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Spatie\EventProjector\ShouldBeStored;
Expand All @@ -27,7 +28,7 @@ public static function createForEvent(ShouldBeStored $event, string $uuid = null
{
$storedEvent = new static();
$storedEvent->aggregate_uuid = $uuid;
$storedEvent->event_class = get_class($event);
$storedEvent->event_class = static::getEventClass(get_class($event));
$storedEvent->attributes['event_properties'] = app(EventSerializer::class)->serialize(clone $event);
$storedEvent->meta_data = [];
$storedEvent->created_at = Carbon::now();
Expand All @@ -37,6 +38,11 @@ public static function createForEvent(ShouldBeStored $event, string $uuid = null
return $storedEvent;
}

public function getEventClassAttribute(string $value): string
{
return static::getActualClassForEvent($value);
}

public function getEventAttribute(): ShouldBeStored
{
try {
Expand Down Expand Up @@ -100,4 +106,20 @@ public static function store(ShouldBeStored $event, string $uuid = null): void
{
static::storeMany([$event], $uuid);
}

protected static function getEventClass(string $class): string
{
$map = config('event-projector.event_class_map', []);

if (! empty($map) && in_array($class, $map)) {
return array_search($class, $map, true);
}

return $class;
}

protected static function getActualClassForEvent(string $class): string
{
return Arr::get(config('event-projector.event_class_map', []), $class, $class);
}
}
21 changes: 21 additions & 0 deletions tests/EventSubscriberTest.php
Expand Up @@ -49,6 +49,27 @@ public function it_will_log_events_that_implement_ShouldBeStored()
$this->assertEquals($this->account->id, $storedEvent->event->account->id);
}

/** @test * */
public function it_will_log_events_that_implement_ShouldBeStored_with_a_map()
{
$this->setConfig('event-projector.event_class_map', [
'money_added' => MoneyAddedEvent::class,
]);

event(new MoneyAddedEvent($this->account, 1234));

$this->assertCount(1, StoredEvent::get());

$storedEvent = StoredEvent::first();

$this->assertEquals(MoneyAddedEvent::class, $storedEvent->event_class);
$this->assertEquals('money_added', $storedEvent->getAttributes()['event_class']);

$this->assertInstanceOf(MoneyAddedEvent::class, $storedEvent->event);
$this->assertEquals(1234, $storedEvent->event->amount);
$this->assertEquals($this->account->id, $storedEvent->event->account->id);
}

/** @test */
public function it_will_not_store_events_without_the_ShouldBeStored_interface()
{
Expand Down
13 changes: 13 additions & 0 deletions tests/Models/StoredEventTest.php
Expand Up @@ -45,6 +45,19 @@ public function it_will_throw_a_human_readable_exception_when_the_event_couldnt_
StoredEvent::first()->event;
}

/** @test * */
public function it_will_store_the_alias_when_a_classname_is_found_in_the_event_class_map()
{
$this->setConfig('event-projector.event_class_map', [
'money_added' => MoneyAddedEvent::class,
]);

$this->fireEvents();

$this->assertEquals(MoneyAddedEvent::class, StoredEvent::first()->event_class);
$this->assertEquals('money_added', StoredEvent::first()->getAttributes()['event_class']);
}

public function fireEvents(int $number = 1, string $className = MoneyAddedEvent::class)
{
foreach (range(1, $number) as $i) {
Expand Down

0 comments on commit af6fa8b

Please sign in to comment.