PHP 8.2 introduced readonly as a class-level modifier. Every property in a readonly class is implicitly readonly — perfect for value objects.
Combined with constructor property promotion you get one-line value objects: readonly class Money { public function __construct(public int $cents, public string $currency) {} }.
The constraint: properties can be assigned exactly once, from inside the declaring class. Cloning a readonly object still works via __clone() mutation.