cjsaylor / libdomain
此包已弃用,不再维护。未建议替代包。
PHP 类和特性,用于简化领域驱动设计。
4.0.0
2018-07-23 11:21 UTC
Requires
- php: >=7.1
Requires (Dev)
- phpunit/phpunit: ^6
README
Libdomain 是一个 PHP 库,用于简化 领域驱动开发。
核心概念
此库包含以下抽象类
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.