php-ddd/domain-event

用于管理领域和事件的库

v1.0.1 2015-08-08 08:49 UTC

This package is not auto-updated.

Last update: 2024-09-14 17:03:57 UTC


README

此库允许您集中精力在应用程序最重要的部分:领域。
根据Eric Evans的《领域驱动设计》一书,您的领域应由聚合组成。
每个聚合由一个AggregateRoot和一些ObjectValue组成。

此库专注于AggregateRoot,并提供管理聚合发生事件的帮助程序。

用法

以下示例将更好地解释此库的目的

use PhpDDD\Domain\AbstractAggregateRoot;

class PurchaseOrder extends AbstractAggregateRoot
{
    /**
     * @var mixed
     */
    private $customerId;

    /**
     * Try to create a new PurchaseOrder for a client.
     */
    public function __construct(Customer $customer)
    {
        // Tests that some business rules are followed.
        if (false === $customer->isActive()) {
            throw new MyDomainException('The customer need to be active.');
        }
        
        // ...
        // Since every rules are validated, we can simulate the creation of the Event associated
        // This allows us to have less redundant code
        
        $this->apply(new PurchaseOrderCreated($customer, new DateTime()));
        
        // This is equivalent as
        // $this->customerId = $customer->getId();
        // $this->events[] = new PurchaseOrderCreated($customer, new DateTime());
        // but we are not allowing to add event directly.
    }
    
    /**
     * The apply() method will automatically call this method.
     * Since it's an event you should never do some tests in this method.
     * Try to think that an Event is something that happened in the past.
     * You can not modify what happened. The only thing that you can do is create another event to compensate.
     */
    protected function applyPurchaseOrderCreated(PurchaseOrderCreated $event)
    {
        $this->customerId = $event->getCustomer()->getId();
    }
}

这种方法的优点是,您然后可以监听AggregateRoot产生的每个事件,并进行一些与业务领域不直接相关的工作,如发送电子邮件。

use PhpDDD\Domain\Event\Listener\AbstractEventListener;

class SendEmailOnPurchaseOrderCreated extends AbstractEventListener
{
    private $mailer;
    
    public function __construct($mailer)
    {
        $this->mailer = $mailer;
    }
    
    /**
     * {@inheritDoc}
     */
    public function getSupportedEventClassName()
    {
        return 'PurchaseOrderCreated'; // Should be the fully qualified class name of the event
    }
    
    /**
     * {@inheritDoc}
     */
    public function handle(EventInterface $event)
    {
        $this->mailer->send('to@you.com', 'Purchase order created for customer #' . $event->getCustomer()->getId());
    }
}

为了使项目知道有一个EventListener绑定到事件,您应该使用EventBus

// first the locator
$locator = new \PhpDDD\Domain\Event\Listener\Locator\EventListenerLocator();
$locator->register('PurchaseOrderCreated', new SendEmailOnPurchaseOrderCreated(/* $mailer */));

// then the EventBus
$bus = new \PhpDDD\Domain\Event\Bus\EventBus($locator);

// do what you need to do on your Domain
$aggregateRoot = new PurchaseOrder(new Customer(1));

// Then apply EventListeners
$events = $aggregateRoot->pullEvents(); // this will clear the list of event in your AggregateRoot so an Event is trigger only once

// You can have more than one event at a time.
foreach($events as $event) {
    $bus->publish($event);
}