superbalist/php-event-pubsub

此包已被废弃,不再维护。未建议替代包。

基于pub/sub的事件协议和实现

4.0.3 2017-09-14 14:58 UTC

README

基于pub/sub的事件协议和实现

Author Build Status StyleCI Software License Packagist Version Total Downloads

这个库基于php-pubsub包,并添加了对通过pub/sub通道监听和调度事件的支持。

安装

composer require superbalist/php-event-pubsub

集成

想要快速开始?查看以下集成

用法

简单事件

SimpleEvent是一个接受名称和可选属性的事件。

// create a new event manager
$adapter = new \Superbalist\PubSub\Adapters\LocalPubSubAdapter();
$translator = new \Superbalist\EventPubSub\Translators\SimpleEventMessageTranslator();
$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator);

// dispatch an event
$event = new \Superbalist\EventPubSub\Events\SimpleEvent(
    'user.created',
    [
        'user' => [
            'id' => 1456,
            'first_name' => 'Joe',
            'last_name' => 'Soap',
            'email' => 'joe.soap@example.org',
        ],
    ]
);
$manager->dispatch('events', $event);

// dispatch multiple events
$events = [
    new \Superbalist\EventPubSub\Events\SimpleEvent(
        'user.created',
        [
            'user' => [
                // ...
            ],
        ]
    ),
    new \Superbalist\EventPubSub\Events\SimpleEvent(
        'user.created',
        [
            'user' => [
                // ...
            ],
        ]
    ),
];
$manager->dispatchBatch('events', $events);

// listen for an event
$manager->listen('events', 'user.created', function (\Superbalist\EventPubSub\EventInterface $event) {
    var_dump($event->getName());
    var_dump($event->getAttribute('user'));
});

// listen for all events on the channel
$manager->listen('events', '*', function (\Superbalist\EventPubSub\EventInterface $event) {
    var_dump($event->getName());
});

主题事件

TopicEvent是一个接受主题、名称、版本和可选属性的事件。

// create a new event manager
$adapter = new \Superbalist\PubSub\Adapters\LocalPubSubAdapter();
$translator = new \Superbalist\EventPubSub\Translators\TopicEventMessageTranslator();
$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator);

// dispatch an event
$event = new \Superbalist\EventPubSub\Events\TopicEvent(
    'user',
    'created',
    '1.0',
    [
        'user' => [
            'id' => 1456,
            'first_name' => 'Joe',
            'last_name' => 'Soap',
            'email' => 'joe.soap@example.org',
        ],
    ]
);
$manager->dispatch('events', $event);

// listen for an event on a topic
$manager->listen('events', 'user/created', function (\Superbalist\EventPubSub\EventInterface $event) {
    // ...
});

// listen for an event on a topic matching the given version
$manager->listen('events', 'user/created/1.0', function (\Superbalist\EventPubSub\EventInterface $event) {
    // ...
});

// listen for all events on a topic
$manager->listen('events', 'user/*', function (\Superbalist\EventPubSub\EventInterface $event) {
    // ...
});

// listen for all events on the channel
$manager->listen('events', '*', function (\Superbalist\EventPubSub\EventInterface $event) {
    // ...
});

模式事件

SchemaEventTopicEvent的扩展,接受模式(schema)和可选属性。主题、名称和版本从模式中推导而来。

模式必须是以下格式:(协议)://(......)?/events/(主题)/(通道)/(版本).json

// create a new event manager
$adapter = new \Superbalist\PubSub\Adapters\LocalPubSubAdapter();

$translator = new \Superbalist\EventPubSub\Translators\SchemaEventMessageTranslator();

$schemas = [
    'events/user/created/1.0.json' => json_encode([
        '$schema' => 'https://json-schema.fullstack.org.cn/draft-04/schema#',
        'title' => 'My Schema',
        'type' => 'object',
        'properties' => [
            'schema' => [
                'type' => 'string',
            ],
            'user' => [
                'type' => 'object',
            ],
        ],
        'required' => [
            'schema',
            'user',
        ],
    ]),
];
$loader = new \League\JsonGuard\Loaders\ArrayLoader($schemas);

$dereferencer = new \League\JsonGuard\Dereferencer();
$dereferencer->registerLoader($loader, 'array');

$validator = new \Superbalist\EventPubSub\Validators\JSONSchemaEventValidator($dereferencer);

$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator, $validator);

// dispatch an event
$event = new \Superbalist\EventPubSub\Events\SchemaEvent(
    'http://schemas.my-website.org/events/user/created/1.0.json',
    [
        'user' => [
            'id' => 1456,
            'first_name' => 'Joe',
            'last_name' => 'Soap',
            'email' => 'joe.soap@example.org',
        ],
    ]
);
$manager->dispatch('events', $event);

// the listen expressions are the same as those used for TopicEvents.

自定义事件

您可以通过编写一个实现EventInterface接口的类来轻松使用自定义事件结构。然后您需要编写一个自定义翻译器来将传入的消息转换为您自己的事件对象。

您的事件必须实现以下方法。

/**
 * Return the event name.
 *
 * @return string
 */
public function getName();

/**
 * Return all event attributes.
 *
 * @return array
 */
public function getAttributes();

/**
 * Return an event attribute.
 *
 * @param string $name
 * @return mixed
 */
public function getAttribute($name);

/**
 * Set an event attribute.
 *
 * @param string|array $name
 * @param mixed $value
 */
public function setAttribute($name, $value = null);

/**
 * Check whether or not an event has an attribute.
 *
 * @param string $name
 * @return bool
 */
public function hasAttribute($name);

/**
 * Check whether or not the event matches the given expression.
 *
 * @param string $expr
 * @return bool
 */
public function matches($expr);

/**
 * Return the event in a message format ready for publishing.
 *
 * @return mixed
 */
public function toMessage();

翻译器

翻译器用于将传入的消息转换为事件。

该包附带了一个SimpleEventMessageTranslatorTopicEventMessageTranslatorSchemaEventMessageTranslator

自定义翻译器

您可以通过实现MessageTranslatorInterface接口来轻松编写自己的翻译器。

您的翻译器必须实现以下方法。

/**
 * @param mixed $message
 * @return null|EventInterface
 */
public function translate($message);

验证器

验证器是一个可选组件,用于在调度事件时验证事件。

JSONSchemaEventValidator

此包附带了一个JSONSchemaEventValidator,它适用于SchemaEvent类型的事件。

此验证器使用JSON Schema SpecJSON Guard PHP包来验证事件。

请参阅上面的“模式事件”部分和JSON Guard文档以获取用法示例。

自定义验证器

您可以通过实现EventValidatorInterface接口来编写自己的验证器。

您的验证器必须实现以下方法。

/**
 * @param EventInterface $event
 * @return ValidationResult
 */
public function validate(EventInterface $event);

属性注入器

属性注入器允许您在事件调度时自动将属性注入到事件中。

该库附带了一些内置的注入器。

  • DateAttributeInjector - 注入一个date键,其值为ISO 8601日期时间
  • GenericAttributeInjector - 注入一个自定义的keyvalue
  • HostnameAttributeInjector - 注入一个hostname键,其值为服务器主机名
  • Uuid4AttributeInjector - 注入一个uuid键,其值为UUID-4

您可以通过实现AttributeInjectorInterface或通过传递一个可调用的函数(该函数返回一个包含'key'和'value'的数组)到事件管理器来编写自己的注入器。

您的注入器必须实现以下方法。

/**
 * @return string
 */
public function getAttributeKey();

/**
 * @return mixed
 */
public function getAttributeValue();

这里是一个使用示例,展示了类和可调用函数。

自定义类

use Superbalist\EventPubSub\AttributeInjectorInterface;

class UserAttributeInjector implements AttributeInjectorInterface
{
    /**
     * @return string
     */
    public function getAttributeKey()
    {
        return "user";
    }

    /**
     * @return mixed
     */
    public function getAttributeValue()
    {
        return [
            'id' => 2416334,
            'email' => 'john.doe@example.org',
            'first_name' => 'John',
            'last_name' => 'Doe',
        ];
    }
}

// create a new event manager
$adapter = new \Superbalist\PubSub\Adapters\LocalPubSubAdapter();
$translator = new \Superbalist\EventPubSub\Translators\SimpleEventMessageTranslator();
$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator);

$manager->addAttributeInjector(new UserAttributeInjector());

// or
$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator, null, [new UserAttributeInjector()]);

可调用函数

// create a new event manager
$adapter = new \Superbalist\PubSub\Adapters\LocalPubSubAdapter();
$translator = new \Superbalist\EventPubSub\Translators\SimpleEventMessageTranslator();
$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator);

$manager->addAttributeInjector(function () {
    return [
        'key' => 'user',
        'value' => [
            'id' => 2416334,
            'email' => 'john.doe@example.org',
            'first_name' => 'John',
            'last_name' => 'Doe',
        ],
    ];
});

错误处理

该库支持错误处理器,用于处理事件转换失败、监听表达式失败和验证失败的情况。

您可以将可调用函数传递给EventManager构造函数,或按照以下方式设置

// create a new event manager
$adapter = new \Superbalist\PubSub\Adapters\LocalPubSubAdapter();
$translator = new \Superbalist\EventPubSub\Translators\SimpleEventMessageTranslator();
$manager = new \Superbalist\EventPubSub\EventManager($adapter, $translator);

// hook into translation failures
$manager->setTranslateFailHandler(function ($message) {
    // the message failed to translate into an event
});

// hook into listen expression failures
$manager->setListenExprFailHandler(function (\Superbalist\EventPubSub\EventInterface $event, $expr) {
    // the event didn't match the listen expression
    // this isn't really an error, but can be useful for debug
});

// hook into validation failures
$manager->setValidationFailHandler(function (\Superbalist\EventPubSub\ValidationResult $result) {
    // the event failed validation
    var_dump($result->errors());
});

示例

该库提供了不同类型事件的示例和一个Dockerfile,用于运行示例脚本。

运行make up

您将进入/opt/php-event-pubsub目录下的bash提示符。

要运行示例

$ php examples/SimpleEventExample.php
$ php examples/TopicEventExample.php
$ php examples/SchemaEventExample.php