轻松在项目中实现领域事件

1.0 2014-10-01 00:41 UTC

This package is not auto-updated.

Last update: 2024-09-10 02:12:28 UTC


README

Build Status Packagist Version Packagist Downloads Packagist License

StudioIgnis Evt

轻松在项目中实现领域事件。

最初受laracasts/commander启发

安装

通过composer添加包到您的composer.json文件中安装

{
    "require": {
        "studioignis/evt": "~1.0"
    }
}

或者使用以下命令

$ composer require studioignis/evt:~1.0

用法

非常简单,您只需要事件调度程序实例,然后就可以开始添加监听器了

$dispatcher = new StudioIgnis\Evt\EventDispatcher;
$dispatcher->addListener(
    'UserWasRegistered',
    new SendEmailUponUserRegistration($mailer)
);

之后,您就可以开始调度事件了

$dispatcher->dispatch([new Acme\Events\UserWasRegistered($name, $email)]);

您可以一次性调度多个事件,这就是为什么dispatch()需要一个事件数组的原因。

事件

事件是简单的DTO(数据传输对象),但应遵守StudioIgnis\Evt\Event契约。此契约只声明一个方法:getEventName(),用于获取事件的名称,以确定要运行哪些监听器。

提供了一个特质,它使用简单的默认策略满足此契约。如果您的活动是Acme\Events\UserWasRegistered,则特质的getEventName()将使用事件类的短名称作为事件名称,即UserWasRegistered

以下是一个示例

namespace Acme\Events;

use StudioIgnis\Evt\Event;
use StudioIgnis\Evt\Traits\EventName;

class UserWasRegistered implements Event
{
    use EventName;
    
    private $name;
    
    private $email;
    
    public function __construct($name, $email)
    {
        $this->name = $name;
        $this->email = $email;
    }
    
    public function getName()
    {
        return $this->name;
    }
    
    public function getEmail()
    {
        return $this->email;
    }
}

如果我们没有使用EventName特质,我们就必须添加一个返回事件名称的getEventName()方法。您不需要使用特质,它只是方便,您可能需要提供一个自定义名称,在这种情况下您就不会使用它。

监听器

事件监听器是一个应该遵守事件监听器契约的类。此契约定义了一个方法:handle(Event $event),它期望接收已调度的事件。

namespace Acme\Events;

use StudioIgnis\Evt\EventListener;

class SendEmailUponUserRegistration implements EventListener
{
    private $mailer;
    
    public function __construct($mailer)
    {
        // Your hypothetical mailer class
        $this->mailer = $mailer;
    }
    
    public function handle(Event $event)
    {
        $this->mailer->sendWelcomeEmail($event->getEmail(), $event->getName());
    }
}

我知道,我知道,每个人都使用相同的示例,请原谅我缺乏创意 :D

在调度时解析监听器

您可以通过传递字符串抽象而不是传递已实例化的监听器

$dispatcher->addListener('SomeEvent', 'Acme\Events\SomeListener');
// or
$dispatcher->addListener('SomeEvent', 'listeners.some_event_listener');

这样,监听器将在事件被调度时被实例化。

但是,为了实现这一点,调度器必须与应用程序容器一起创建

$dispatcher = new Dispatcher($container);

容器必须遵守\StudioIgnis\Evt\Support\Container契约。

为Laravel应用程序提供了一个默认容器,因此当从IoC容器中解析调度器时,这将自动完成。

从您的实体中引发事件

您很可能会从您的实体中引发事件。为此,您有方便的HasDomainEvents特质。

此特质添加了两个方法:raise(Event $event)releaseEvents()。如名称所示,raise(Event $event)添加待调度的事件。 releaseEvents()返回引发的事件并清除待处理的事件。

让我们看看一个示例

namespace Acme;

use StudioIgnis\Evt\Traits\HasDomainEvents;

class User implements EventListener
{
    use HasDomainEvents;
    
    public function __construct($name, $email)
    {
        // Init your params, invariants, etc
        
        $this->raise(new Events\UserWasRegistered($name, $email));
    }
}

现在(可能在命令处理程序类中)您可以这样做

$dispatcher->dispatch($user->releaseEvents());

Laravel集成

此包包含Laravel框架的供应商。您需要将其添加到您的config/app.php文件中

'StudioIgnis\Evt\Laravel\ServiceProvider'

这样,您可以将其作为依赖项注入,并将从IoC容器中自动解析出来

class SomeController extends Controller
{
    private $dispatcher;
    
    public function __construct(Dispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
}

主要好处,如前所述,是将容器传递给调度器,这使得您可以将抽象作为监听器传递以从容器中解析。

替换调度器

如果您需要使用自己的自定义调度器,您可以在配置中更改它。为此,您需要发布此包的配置

$ php artisan config:publish studioignis/evt

并将'dispatcher'键更改为指向您的调度器类。

return [
    /**
     * Which concrete dispatcher implementation to map to
     * StudioIgnis\Evt\Dispatcher contract.
     */
    'dispatcher' => 'StudioIgnis\Evt\EventDispatcher',
];

许可证

版权(c)2014 Luciano Longo

本软件及其相关文档文件(以下简称“软件”)的副本的任何个人,在此免费获得授权,不受限制地处理软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或销售软件的副本,并允许软件提供者进行此类操作,但须遵守以下条件

上述版权声明和本许可声明应包含在软件的所有副本或主要部分中。

软件按“原样”提供,不提供任何形式的保证,无论是明示的还是暗示的,包括但不限于适销性、适用于特定目的和非侵权性保证。在任何情况下,作者或版权持有人不对任何索赔、损害或其他责任承担责任,无论该责任是基于合同、侵权或其他原因,是否与软件或其使用或其他相关活动有关。