mad654/php-event-store

提供类来表示对象状态变化作为事件,并将它们存储在基于文件的流中

1.0.1 2019-03-09 18:36 UTC

This package is auto-updated.

Last update: 2024-09-10 08:11:14 UTC


README

使用事件源进行持久化的简单PHP事件存储实现。

它提供了类来表示对象状态变化作为事件,并将它们存储在基于文件的流中。

安装

您可以通过在composer.json中添加“mad654/php-event-store”: "dev-master"作为要求来使用composer安装mad654/php-event-store。

示例

要查看完整的工作示例,请查看src/example。在您的vagrant虚拟机中,您可以使用它如下所示

# create storage folder
mkdir -p /tmp/var/eventstore-example/ 

# create a new instance of LightSwitch with id 'kitchen'
src/example/bin/console.php init kitchen

# switch on/off on 'kitchen'
src/example/bin/console.php switch kitchen --on
src/example/bin/console.php switch kitchen --off

# render history of 'kitchen'
src/example/bin/console.php history kitchen

步骤

让我们以这个小例子来接触所有新内容。假设您想控制厨房的灯光,为此您已经构建了一些开关。您需要的只是一个可以控制状态并跨多个请求保持其当前状态的对象

class LightSwitch {	
    private $state = false;
    
    public function isOn(): bool {
        return $this->state;
    }
    
    public function switchOn()
    {
        if ($this->state === true) return;
        // do some stuff which does the hard work
        $this->state = true;
    }
    
    public function switchOff()
    {
        if ($this->state === false) return;
         // do some stuff which does the hard work
        $this->state = false;
    }
}

这是一个好的开始,但现在您需要一种持久化状态的方法。

EventSourcedObject

您不需要创建数据库,只需扩展您的类以实现EventSourcedObject接口。EventSourcedObject是一个简单的对象,它应该在下一个请求中可用,为此它可以发布其事件作为流,并且可以从零开始根据事件构建

<?php
use mad654\eventstore\Event;
use mad654\eventstore\Event\StateChanged;
use mad654\eventstore\EventSourcedObject;
use mad654\eventstore\EventStream\AutoTrackingEventSourcedObjectTrait;
use mad654\eventstore\SubjectId;

class LightSwitch implements EventSourcedObject
{
    use AutoTrackingEventSourcedObjectTrait;

    /**
     * @var bool
     */
    private $state;

    public function __construct(SubjectId $id)
    {
        $this->init($id, ['state' => false]);
    }

    public function isOn(): bool
    {
        return $this->state;
    }

    public function switchOn(): void
    {
        if ($this->state) return;
        $this->record(new StateChanged($this->subjectId(), ['state' => true]));
    }

    public function switchOff(): void
    {
        if (!$this->state) return;
        $this->record(new StateChanged($this->subjectId(), ['state' => false]));
    }

    public function on(Event $event): void
    {
        $this->state = $event->get('state', $this->state);
    }

}

因此,您将直接更改成员变量,而是使用事件,如下所示switchOn。您将记录一个事件,并在on函数中更新您的状态,该函数由record函数自动调用。

如果您想了解更多详细信息,请查看AutoTrackingEventSourcedObjectTrait,它应该是所有事件源对象的良好起点,并减少样板代码。

EventSourcedObjectStore

use mad654\eventstore\FileEventStream\FileEventStreamFactory;
use mad654\eventstore\EventObjectStore;

$factory = new FileEventStreamFactory("/tmp/eventstore-example");
$store = new EventSourcedObjectStore($factory);

EventSourcedObjectStore提供了一个简单的API,允许您保存和加载实现EventEmitter接口的对象

$store->attach($someEventSourcedObject);
unset($someEventSourcedObject);
$id = StringSubjectId::fromString('id-of-some-object');
$someEventEmitter = $store->get($id);

如果'$someEventSourcedObject'实现正确,它应该在unset()调用前后具有相同的状态。

根据定义,EventSourcedObjectStore只能通过ID存储和检索对象。在这里,您可以找到解决方案以进行搜索...

事件

在这个例子中,我们使用StateChanged事件,在生产中,您应该创建此类的子类以更精确地表达发生了什么。

通常事件是不可变的。

汇总

use mad654\eventstore\FileEventStream\FileEventStreamFactory;
use mad654\eventstore\EventObjectStore;

$factory = new FileEventStreamFactory("/tmp/eventstore-example");
$store = new EventSourcedObjectStore($factory);

$switch = new LightSwitch('kitchen');
$store->attach($switch);

在稍后的另一个请求中,您想打开厨房的灯

$store->get(StringSubjectId::fromString('kitchen'))->switchOn();

然后您再次将其关闭

$store->get(StringSubjectId::fromString('kitchen'))->switchOff();

然后...

然后...

现在您想知道为什么您的电费这么贵 - 让我们看看历史记录

$renderer = new ArrayEventStreamRenderer();
$store->get(StringSubjectId::fromString('kitchen'))->history($renderer);
$data = $renderer->toArray();

// use symonfy command style to render a nice table on command line
$io = new SymfonyStyle($input, $output);
$io->table(
    ['nr', 'timestamp', 'event_type', 'id', 'property', 'new_state'],
    $data
);

# nr | timestamp           | event_type   | id       | property | new_state
# 1  | 2018-12-01 18:10:00 | StateChanged | kittchen | state    | on
# 2  | 2018-12-01 18:12:00 | StateChanged | kittchen | state    | off
# 3  | 2018-12-01 19:30:00 | StateChanged | kittchen | state    | on
# 4  | 2018-12-03 18:10:00 | StateChanged | kittchen | state    | off

开发

cd local_develop
vagrant up
vagrant ssh

在vagrant虚拟机内部

composer install
make test