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, never CoordinateValue or CoordinateVO. A project on the domain layout keeps its ValueObjects/ (see laravel-architecture).
  • Immutable. A readonly class with 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 separate validate() or isValid() for a caller to forget.
  • Named constructors for other inputs. fromString(), fromArray() parse their input, then call new 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): bool that 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. Stringable when it's printed, JsonSerializable when it's serialised, Arrayable when it becomes an array. A __toString() that a named constructor can parse back makes the pair round-trip.

Example

<?php
Installs
52
GitHub Stars
15
First Seen
Mar 27, 2026