|
1 | | -# php-domain-model |
| 1 | +# Domain Model |
| 2 | + |
| 3 | +[](https://github.com/ComplexHeart/php-domain-model/actions/workflows/test.yml) |
| 4 | +[](https://codecov.io/gh/ComplexHeart/php-domain-model) |
| 5 | + |
| 6 | +## Modeling Aggregates, Entities and Value Objects |
| 7 | + |
| 8 | +Complex Heart allows you to model your domain Aggregates, Entities, and Value Objects using a set of traits. Great, but |
| 9 | +why traits and not classes? Well, sometimes you have some kind of inheritance in your classes. Being forced to use a |
| 10 | +certain base class is too invasive and personally, I don't like it. By using a set of traits and interfaces you have all |
| 11 | +the functionality you need without compromising the essence of your own domain. |
| 12 | + |
| 13 | +Let's see a very basic example: |
| 14 | + |
| 15 | +```php |
| 16 | +use ComplexHeart\Contracts\Domain\Model\ValueObject; |
| 17 | +use ComplexHeart\Domain\Model\Traits\IsValueObject; |
| 18 | + |
| 19 | +/** |
| 20 | + * Class Color |
| 21 | + * @method string value() |
| 22 | + */ |
| 23 | +final class Color implements ValueObject |
| 24 | +{ |
| 25 | + use IsValueObject; |
| 26 | + |
| 27 | + private string $value; |
| 28 | + |
| 29 | + public function __construct(string $value) { |
| 30 | + $this->initialize(['value' => $value]); |
| 31 | + } |
| 32 | + |
| 33 | + protected function invariantValueMustBeHexadecimal(): bool { |
| 34 | + return preg_match('/^#(?:[0-9a-fA-F]{3}){1,2}$/', $this->value) === 1; |
| 35 | + } |
| 36 | + |
| 37 | + public function __toString(): string { |
| 38 | + return $this->value(); |
| 39 | + } |
| 40 | +} |
| 41 | + |
| 42 | +$red = new Color('#ff0000'); |
| 43 | +$red->equals(new Color('#00ff00')); // false |
| 44 | +$red->value(); // #ff0000 |
| 45 | +$magenta = new Color('ff00ff'); // Exception InvariantViolation: Value must be hexadecimal. |
| 46 | +``` |
| 47 | + |
| 48 | +To define a Value Object you only need to use the `IsValueObject` trait. This trait will allow you to use some functions |
| 49 | +like `equals()` that will automatically compare the value of the objects. The `initialize()` is also available, it will |
| 50 | +allow you to run invariant validations against the object values. Optionally, and recommended, you can use |
| 51 | +the `ValueObject` interface. |
| 52 | + |
| 53 | +The available traits are: |
| 54 | + |
| 55 | +- `HasAttributes` Provide some functionality to manage attributes. |
| 56 | +- `HasEquality` Provide functionality to handle equality between objects. |
| 57 | +- `HasInvariants` Allow invariant checking on instantiation (Guard Clause). |
| 58 | +- `HasIdentity` Define the Entity/Aggregate identity. |
| 59 | +- `HasDomainEvents` Provide domain event management. |
| 60 | + |
| 61 | +On top of those base traits **Complex Heart** provide ready to use compositions: |
| 62 | + |
| 63 | +- `IsModel` composed by `HasAttributes` and `HasInvariants`. |
| 64 | +- `IsValueObject` composed by `IsModel` and `HasEquality`. |
| 65 | +- `IsEntity` composed by `IsModel`, `HasIdentity`, `HasEquality`. |
| 66 | +- `IsAggregate` composed by `IsEntity`, `HasDomainEvents`. |
0 commit comments