https://github.com/othercodes/ddd-value-object
Small library to easily apply the Value Object Pattern.
https://github.com/othercodes/ddd-value-object
ddd-architecture ddd-patterns value-object
Last synced: 10 months ago
JSON representation
Small library to easily apply the Value Object Pattern.
- Host: GitHub
- URL: https://github.com/othercodes/ddd-value-object
- Owner: othercodes
- License: mit
- Created: 2020-09-28T10:09:32.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2020-11-16T10:35:44.000Z (about 5 years ago)
- Last Synced: 2025-01-24T08:12:30.203Z (12 months ago)
- Topics: ddd-architecture, ddd-patterns, value-object
- Language: PHP
- Homepage:
- Size: 26.4 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# DDD Value Object
 [](https://packagist.org/packages/othercodes/ddd-value-object) [](https://codecov.io/gh/othercodes/ddd-value-object)
Small library to easily manage the Value Object Pattern.
## Installation
Use the following command to install with `composer`:
```bash
composer require othercode/ddd-value-object
```
This will automatically get the latest version and configure a `composer.json` file.
Alternatively you can create the following `composer.json` file and run `composer install` to install it.
```bash
{
"require": {
"othercode/ddd-value-object": "*"
}
}
```
## Usage
Build a Value object is quite simple, you just need to extend the `ValueObject` Next, initialize the values in the
constructor by using the `initialize` method. Finally, add invariant rules as protected method, using the prefix
`invariant` (this prefix can be customized) and execute them with the `checkInvariants` method.
```php
initialize([
'amount' => $amount,
'magnitude' => $magnitude
]);
$this->checkInvariants();
}
protected function invariantSpeedMustBeGreaterThanZero(): bool
{
return $this->amount() > 0;
}
protected function invariantMagnitudeMustBeValid(): bool
{
return in_array($this->magnitude(), [
self::KILOMETERS_PER_HOUR,
self::MILES_PER_HOUR
]);
}
public function amount(): int
{
return $this->get('amount');
}
public function magnitude(): string
{
return $this->get('magnitude');
}
public function increase(Speed $speed): self
{
if ($speed->magnitude() !== $this->magnitude()) {
throw new InvalidArgumentException('The given magnitude is not valid.');
}
return new self($this->amount() + $speed->amount(), $this->magnitude());
}
public function __toString(): string
{
return $this->amount() . $this->magnitude();
}
}
```
### Equality
Value equality is computed by serializing the object and hashing it with the sha256 algorithm. Alternatively, you can
override `equalityHash` to calculate a proper hash for the object. This hash is used to check if the value objects are
equals or not.
```php
amount(), $this->magnitude());
}
// ...
}
```
### Immutability
The immutability property blocks any attempt of value modification, that will end in exception:
```php
$s = new Speed(120, 'km/h');
$s->amount = 123;
// PHP Fatal error: Uncaught OtherCode\DDDValueObject\Exceptions\ImmutableValueException: Illegal attempt to change immutable value.
```
You can customize the exception that will be thrown by overriding the `immutabilityException` property. The same happens
with the error message, you just need to override the `immutabilityMessages` property.
```php
'You shall not update this value!.',
];
// ...
}
```
### Invariants
The invariants methods must return a boolean value, `true` if the invariant is successfully, `false` otherwise. If any
in variant is violated you will get an exception:
```php
amount() < 0) {
throw new InvalidArgumentException('The given speed value is not valid');
}
return true;
}
// ...
}
$s = new Speed(-1, 'm/s');
// PHP Fatal error: Uncaught InvalidArgumentException: Unable to create Speed value object due:
// The given speed value is not valid
// invariant magnitude must be valid
```
Additionally, you can fully customize how the invariant violation are managed by passing a custom function to the
`checkInvariants` method:
```php
initialize([
'amount' => $amount,
'magnitude' => $magnitude
]);
$this->checkInvariants(function (array $violations) {
throw new RuntimeException("Epic fail due:\n-" . implode("\n-", $violations) . "\n");
});
}
protected function invariantSpeedMustBeGreaterThanZero(): bool
{
if($this->amount() < 0) {
throw new InvalidArgumentException('The given speed value is not valid');
}
return true;
}
// ...
}
$s = new Speed(-120, 'clicks/s');
// PHP Fatal error: Uncaught RuntimeException: Epic fail due:
// - The given speed value is not valid
// - invariant magnitude must be valid
```