Recommended usage: declare implementations as readonly class (PHP 8.2+) to enforce the * immutability contract at the language level. Mutable properties violate Value Object semantics even when * equals and hashCode still function. Properties must be declared * public; non-public properties are invisible to the equality and hashing engine.

* * @see http://martinfowler.com/bliki/ValueObject.html */ interface ValueObject { /** * Tells whether this Value Object holds the same state as another. * *

Equality is structural and recursive. Two Value Objects are equal when they share the same concrete * class and every paired property is equal: scalars compare by value, nested * {@see ValueObject} properties delegate to their own equals, arrays compare * by keys in the same order with values compared recursively, and enums compare by case identity.

* *

Properties holding objects that are not Value Objects (for example, DateTimeImmutable) * are compared by instance identity. Wrap such values in a dedicated Value Object when value semantics * are desired.

* * @param ValueObject $other The Value Object to compare against. * @return bool True when both Value Objects hold the same structural state, false otherwise. */ public function equals(ValueObject $other): bool; /** * Returns a deterministic hash derived from the Value Object's structural state. * *

The contract pairs with {@see ValueObject::equals}: when $a->equals($b) * holds, $a->hashCode() === $b->hashCode() also holds. Repeated calls on the same instance * return the same hash within a single process. Stability across library versions is not guaranteed.

* * @return string The structural hash of this Value Object. */ public function hashCode(): string; }