laravel-value-objects
Installation
SKILL.md
Laravel Value Objects
A value object is a domain value that has rules: a coordinate, a date range, an email address. It is defined by what it holds, not by an identity, and it can't exist in an invalid state, so code that receives one never checks it again. Behaviour that belongs to the value lives on it. A DTO only carries data between layers (laravel-dtos); once a value has rules or behaviour of its own, it's a value object.
Rules
- Lives in
app/Values/, named for the value.Coordinate,DateRange, neverCoordinateValueorCoordinateVO. A project on the domain layout keeps itsValueObjects/(see laravel-architecture). - Immutable. A
readonly classwith its parts as public promoted properties, and no setters. An operation that would change it returns a new instance. A value handed to several objects can't then change under one of them. - Valid or it doesn't exist. The public constructor validates its input and throws
InvalidArgumentException, or the project's domain exception when a caller is expected to handle it. No separatevalidate()orisValid()for a caller to forget. - Named constructors for other inputs.
fromString(),fromArray()parse their input, then callnew self(...), so validation stays in the constructor. The constructor stays public: it is the plain, validated way in. - Equal by value. An
equals(self $other): boolthat compares the parts. Equality is a domain decision (case, precision, normalisation), and==on objects hides it. - Behaviour belongs on the value. Distance between coordinates, whether a range contains a date, formatting the value itself. Anything that needs the database or a service stays in an action.
- Interfaces only when they're used.
Stringablewhen it's printed,JsonSerializablewhen it's serialised,Arrayablewhen it becomes an array. A__toString()that a named constructor can parse back makes the pair round-trip.
Example
<?php