Table of Contents
9. Value Objects — Small, Immutable Pieces of Meaning
Sometimes the data in our system is not a “thing” like a user or a product.
Sometimes it's just a small piece of meaning
— a value that deserves a name.
A value object is exactly that:
→ a tiny, self‑contained idea that doesn't change once created.
It’s not a folder full of information.
It’s more like a single card
with a specific meaning written on it.
1. Before Any Code: What Is a Value Object?
Imagine we have a small card on our desk that says:
$9.99 USD
This card represents a price.
It's not a user.
It's not a product.
It's just a value — but a meaningful one.
Now imagine another card:
tony@example.com
That's an email address.
Again, not a “thing” with identity.
Just a value with structure and rules.
A value object is a way to give
these small ideas
a name
and a shape.
2. When a Value Is More Than a Primitive
We could store a price in separate variables like here:
$amount = 9.99; $currency = "USD";
But this raises questions:
- Should
amountandcurrencyalways travel together? - Can the
currencybe anything? - Can the
amountbe negative? - What does this pair of values mean?
When a value starts to feel like a concept,
not just a number or string,
it deserves a name.
That's when we create a value object.
3. Giving the Value a Shape
Here’s a simple value object for money:
class Money { public float $amount; public string $currency; }
This is the same idea as the “folder” metaphor,
but this time the folder is tiny — just enough space for one concept.
Let's explain:
class Money— we're defining a named concept$amount— the numeric part$currency— the currency code
This is the shape of a monetary value.
4. Creating a Value Object
Instantiating an object from the class blueprint:
$price = new Money(); $price->amount = 9.99; $price->currency = "USD";
Just like before:
new Money()creates a small “Money” card$priceis the label we give it$price→amountmeans “look inside and set the amount”$price→currencymeans “look inside and set the currency”
But here's the key difference:
This card represents a value, not a thing.
5. Immutability — The Quiet Superpower
Value objects are meant to be unchanging.
Once we create a value object, we don't modify it.
If we need a different value, we create a new one.
This is what “immutable” means.
Why?
Because values don't have a life story.
They don't evolve.
They simply are.
A price of $9.99 USD doesn't “become” $12.50 USD.
That's a different price.
Immutability keeps our code predictable and safe.
6. Adding Small Behavior
Value objects can also carry tiny pieces of logic that belong to the value.
For example:
class Money { public float $amount; public string $currency; public function add(Money $other): Money { $total = $this->amount + $other->amount; $result = new Money(); $result->amount = $total; $result->currency = $this->currency; return $result; } }
This method (function add):
- looks at the current amount
- adds another amount
- returns a new Money object
Notice:
We don’t change the original.
We create a new one: $result = new Money().
That's immutability in action. The old is not destroyed.
7. When Value Objects Are the Right Tool
Use a value object when the data:
- represents a small concept
- has meaning
- has rules
- should not change
- appears in multiple places
- deserves a name
Examples:
- Email
- Money
- Coordinates
- DateRange
- Temperature
- Percentage
These are not “entities”.
They're pieces of meaning.
8. When Value Objects Are Too Much
Avoid value objects when the data is:
- trivial
- short‑lived
- configuration‑like
- not meaningful
- not reused
Not everything deserves a class.
Use value objects when they clarify, not when they complicate.
9. The Mental Model
Value objects are small, named pieces of meaning.
They don't change.
They don't have identity.
They simply represent a value in a clear, structured way.
Use them when:
- the value has structure
- the value has rules
- the value appears often
- naming the value makes the code clearer
Value objects make our code read like the domain,
not like plumbing.
10- When to Ask AI for a Value Object
The moment when meaning deserves a name
Conversation Example
We start with something simple:
“Create a User with name, email, and phone.”
AI gives us:
class User { public function __construct( public string $name, public string $email, public string $phone ) {} }
Then we ask:
“Validate the email and phone.”
AI responds with something like:
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { … } if (!preg_match('/^\+?[0-9]+$/', $phone)) { … }
Suddenly we see:
- validation logic
- formatting rules
- repeated patterns
- meaning that deserves a home
This is the moment to say:
“Email and Phone are concepts. Give me Value Objects for them.”
AI then produces:
$email = new Email($emailString); $phone = new Phone($phoneString);
Rule of Thumb
If a piece of data has rules, validation, or meaning
— ask for a Value Object.
Summary
This page continues the gentle introduction to modern PHP.
Value objects are about clarity, not complication.
When a value starts to feel like a small idea with meaning, give it a name.
Small names create big understanding, for both humans and AI.
Tony de Araujo —New York
