cjsaylor/libdomain

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

PHP 类和特性,用于简化领域驱动设计。

4.0.0 2018-07-23 11:21 UTC

This package is auto-updated.

Last update: 2020-02-12 13:41:32 UTC


README

Libdomain 是一个 PHP 库,用于简化 领域驱动开发

Build Status

核心概念

此库包含以下抽象类

  • Entity - 实体是可识别的对象。
  • ValueObject - 值不可变的对象。
  • Collection - 实体对象集合。
  • CollectionEntity - 同时作为集合(可识别集合)的实体对象。

在无法扩展抽象类的情况下,所有抽象类的功能都通过特性提供。例如,如果您想使现有的实体具有 ValueObject 的属性,则可以使用 ReadAccessable 特性

use Cjsaylor\Domain\ValueObject\ValueObjectInterface;
use Cjsaylor\Domain\Behavior\ReadAccessable;

class ConcreteEntity implements ValueObjectInterface {
  use ReadAccessable;
}

此时 ConcreteEntity 将成为一个不可变值对象。

示例

实体示例

第一个示例展示了接受一个必须为不可变电子邮件值对象的 email 属性的用户对象。


use \Cjsaylor\Domain\Entity;
use \Cjsaylor\Domain\ValueObject;

class Email extends ValueObject
{
  public function __construct(string $value) {
    // Validate an email address here
    $this['value'] = $value;
  }

  public function __toString() {
    return $this['value'];
  }
}

class User extends Entity
{
  public function offsetSet($offset, $value) : void
  {
    if ($offset === 'email' && !$value instanceof Email) {
      throw new \LogicException('Email must be an email value object!');
    }
    parent::offsetSet($offset, $value);
  }
}

$user = new User([
  'email' => new Email('user@somedomain.com')
]);

CollectionEntity 示例

下面的示例将展示一组具有身份的用户。在这里,我们将使用 CollectionEntity,它既是 Collection 也是 Entity。它将使用第一个示例中定义的 User 实体。

use \Cjsaylor\Domain\CollectionEntity;

class UserGroup extends CollectionEntity
{
  // Here, we set the expectation that this collection can take only users
  public function __construct(array $data = [], User ...$users) {
    parent::__construct($data, ...$users);
  }

  // Here's a method to add additional users post-construction
  public function add(User $user) {
    $this->getItems()[] = $user;
  }
}

$users = [
  new User([
    'id' => 1,
    'email' => new Email('user@somedomain.com')
  ]),
  new User([
    'id' => 2,
    'email' => new Email('user2@somedomain.com')
  ])
];

$userGroup = new UserGroup([
  'id' => 1,
  ...$users
]);

设置器回调示例

让我们修改 User 对象,添加一些自定义设置器回调(自 1.0.1 版本起可用)。这允许我们进行类型提示(并为 Email 值对象执行其他自定义设置逻辑)。

class User extends Entity {

  public function setEmail(Email $email) {
    $this->data['email'] = $email;
  }

}

// Would produce an error as `setEmail` would be called and would not match the type.
$user = new User(['email' => 'user@somedomain.com']);

// Valid
$user = new User(['email' => new Email('user@somedomain.com')]);

具体实体示例

在某些情况下,我们不想在实体上设置额外的属性。为了限制可以设置在实体上的属性,可以实现 PropertyLimitable 接口/特性。

use Cjsaylor\Domain\Behavior\PropertyLimitable;
use Cjsaylor\Domain\Behavior\PropertyLimitTrait;

class User extends Entity implements PropertyLimitable {
  use PropertyLimitTrait;

  public function concreteAttributes() {
    return ['id', 'email'];
  }

}

$user = new User();
$user['id'] = 1; // OK!
$user['first_name'] = 'Chris'; // Has no affect and is not set.