Value Objects, Immutable objects and Doctrine Embeddables
Tags: experience, doctrine, php, symfony
Published: 2024-03-16 10:09:14

---
title: Value Objects, Immutable objects and Doctrine Embeddables
published: true
date: 2015-07-03 17:09:22 UTC
tags: Experience,Doctrine,PHP,Symfony
canonical_url: https://io.serendipityhq.com/experience/php-and-doctrine-immutable-objects-value-objects-and-embeddables/
---

I was thinking about some entities I need, when I came across a very interesting concept: **Immutable Objects**.

The Immutable Objects are very handy to manage the so called **Value Objects**.

In the [Domain Driven Design (DDD)](https://en.wikipedia.org/wiki/Domain-driven_design) properties of an `Entity` can have two different values: other Entities (`Order->getProduct()` – here `Product` is an `Entity` and its properties can change) or simple values (`Product->getPrice()`).

`Price`, in our example, is a simple value, not conceptually an `Entity`. Until now, it probably is a simple property in your Entities (as it was in mine!).  
But, in this second case, the Value Objects play their parts: they represent those values in an immutable state.

In fact, **if you reflect about the data `Price` , you realize that a `Price` is something like “100 Eur”. If you put your attention on the value, you can recognize more than one smaller parts in it: a numeric value – 100 – and a string value – Eur.**  
A `Price` is a `Price` only if we indicate both the numeric part of it (100) and the string part of it (Eur): If we indicate only one of the two, it is not a `Price` because we don’t know how much money does it represents or in which currency the price is expressed.  
**So we need both the “amount” and the “currency” to have a real value. Think it as a “composite value”.**

And the important thing to consider to understand what Immutable stands for: **if in the `Price` we change the amount, we have a different price. If in the `Price` we change the currency, we have, again, a different price.**  
 **But if in a `Product` we change the `Price`, we don’t have a different `Product` but the same one with only a different `Price`.**

## What an Immutable Object is?

Using some words [written by others](http://russellscottwalker.blogspot.it/2013/11/entities-vs-value-objects-and-doctrine-2.html):

> A value object **is a class (usually small**, with just a few properties, and frequently used), **that represents a value which has no identity separate from its properties**. If any one of its properties change, it is no longer the same value.
> 
> An example of a value object is an address. If you change any part of an address, it becomes a different address. Another example would be a price – it might have properties for currency, amount, and payment frequency, but changing any of those would yield a new price.
> 
> **As such, value objects are immutable – their properties cannot change** ( **it is normal to use getters but not setters** for the properties of value objects). **If two value objects have exactly the same properties, they can be regarded as equal**.
> 
> Value objects can have methods, but **the behaviour of a method doesn’t ever change the object’s state**. **If a method needs to change a property, it will return a brand new instance of the value object instead of modifying the existing one**. Methods on a value object can also return other types of value of course (eg. a boolean return value would be typical for a validate method).

So, if a `Product` with a different `Price` is ever the same `Product` (read: THE SAME `Entity` Object, only with a different `Price`. PHP will recognize the different `Price` as a modification of the original `Product` PHP Object), then a different `Price` is something completely different from the previous `Price` (read: it is A DIFFERENT Value Object and for PHP the two Prices are two different and separate objects).

**Those behaviors are obtained writing the code of the two kind of classes (Value Object or `Entity` Object) in different ways and implementing methods with different behaviors when we interact with the Objects.**  
So, knowing the conceptual differences between a pure `Entity` Object class and a Value Object class permits us to write more solid code and better organize our business logic.

### A simple example of an Immutable Object

So, as you can see from the example, this small class respect all the constraints of the definition of “Immutable Object”:

1. Represents a value which has no identity separate from its properties;
2. Its values can be passed only through the `__construct()` and so it hasn’t setter methods (`$this->__set()` is even overridden and with no body to prevent accidental modification to the properties);
3. It returns a brand new instance of `Email` if a change is required.

And it is also really small as class!

## How to manage Value Objects using Doctrine

Starting [since the version 2.5](http://doctrine-orm.readthedocs.org/en/latest/changelog/migration_2_5.html#embeddable-objects), Doctrine supports the use of Value Objects, calling them [Embeddables](http://docs.doctrine-project.org/en/latest/tutorials/embeddables.html).

> Embeddables are classes which are not entities themself, but **are embedded in entities and can also be queried in DQL**. You’ll mostly want to use them to reduce duplication or separating concerns. Value objects such as date range or address are the primary use case for this feature. Embeddables can only contain properties with basic @Column mapping.

This is a simple example of an `AddressEmbeddable` implemented in a dummy `User Entity`:

```
<?php 

/** @Entity */
class User
{
    /** @Embedded(class = "Address") */
    private $address;
}

/** @Embeddable */
class Address
{
    /** @Column(type = "string") */
    private $street;

    /** @Column(type = "string") */
    private $postalCode;

    /** @Column(type = "string") */
    private $city;

    /** @Column(type = "string") */
    private $country;
}
```

### The advantages

Before Embeddable, we could only do two things to manage a Value Object (as the `AddressEmbeddable` is):

1. Create an `Entity` `Address` and use the relation `OneToOne` or `ManyToOne`/`OneToMany` (One `Address` for one `Entity` or, alternatively, one `Entity` with many `Addresses`) to associate the two values;
2. Create the required fields directly as property of the `Entity`.

No other ways. But those two ones have some drawbacks:

The first alternative, create a new `Entity`, means a new table is created in the database (to contain `Addresses`), so the resulting schema is something like this:

```
|---------------------| |--------------------------------------------------|
| TABLE USERS | | TABLE ADDRESSES |
|---------------------| |--------------------------------------------------|
| id | name | Address | | id | street | postal_code | city | country |
|---------------------| |--------------------------------------------------|
| 1 | John | 1 | | 1 | Via di Qui | 12345 | Naples | Italy |
|---------------------| |--------------------------------------------------|

```

Two separate tables linked each other by a foreign key. Each query needs a `JOIN` to get in the same resultset both the User Entity’s data and the email.

The second alternative, create the required fields in each `Entity`, on the other hand, is a solution that doesn’t permit to perform some checks, for example about the validity of passed data (see the example above of the `Email`: when instantiated, the Email (Value) Object checks that the passed data are really an e-mail).  
If you’d like to do this type of checks, you need to repeat the same code in more Entities, and, if you make a change, you have to update the code in more places (not speaking about unit tests!). Not so useful, not so practical, not so intelligent, not so easy.

**Using an Embeddable object, instead, permits you to take advantage of only the benefits of the two methods.**

Embedding the `AddressEmbeddable` in your Entities, will produce a table like this:

```
|-----------------------------------------------------------------------------------|
| TABLE USERS |
|-----------------------------------------------------------------------------------|
| id | name | address_street | address_postal_code | address_city | address_country |
|-----------------------------------------------------------------------------------|
| 1 | John | Via di Qui | 12345 | Naples | Italy |
|-----------------------------------------------------------------------------------|

```

Very useful!

NOTE: The default behavior is to call the column `[embeddale]_[property]` (`[address]_[street]`), but you can [change it](http://docs.doctrine-project.org/en/latest/tutorials/embeddables.html#column-prefixing).

## The last essential question: Which is the best way to represent a domain: an `Entity` or an Embeddable/Value Object?

So, here we come to the very complex question: what kind of class should have I to choose when dealing with such a decision?

Also if the question seems complex, the answer is really simple: it depends ![🙂](https://s.w.org/images/core/emoji/14.0.0/72x72/1f642.png)

> A value object **is a class (usually small**, with just a few properties, and frequently used), **that represents a value which has no identity separate from its properties […]**

So, an `Address` without the postal code has no sense, but a `Company` without an `Address` has.

**A `Price` has no sense without a `Currency`, but a `Product` without a `Price` has.**

**So, use Value Objects/Embeddable each time you have to represent a value composed of more than one information and only the sum of these information has a sense and “creates” the meaning of the value**. You can also use Embeddables in other Embeddables, for example you can use a PostalCodeEmbeddable inside the `AddressEmbeddable` (not tested, but I think it’ll work fine).

Each time you’ll find those kind of objects, you’ll know they cannot be modified in any way and that, if you edit them, you have a new different Object, not the same edited.

The problem: and if, for example, a `Customer` can have more than one `Address` (for example, one time it chose to ship to Italy and the second one it chose to ship to UK)?

The problem arises when the Embeddable is melted into the `Entity` table: only one `Address` is allowed.

### The Real Astonishing Truth: Entities and Value Objects/Embeddable can be used together!

Yes, it is possible to use together Entities and Embeddables.

**So, if a `Customer` can have more than one `Address`, and as you can use Embeddables/Value Objects together with Entities, you’ll have an `AddressEmbeddable` that represents the current state of the value and an `AddressEntity` that represents the collection of those values.**

Something like this:

```
<?php 

namespace AppBundle\Entity;

/** @Entity */
class User
{
    /**
     * @ORM\OneToMany(targetEntity="Address", mappedBy="ofUser")
     */
    private $addresses;
}



<?php 

namespace AppBundle\Entity;

/** @Entity */
class Address
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="addresses")
     * @ORM\JoinColumn(name="of_user", referencedColumnName="id")
     */
    private $ofUser;

    /**
     * @Embedded(class = "AddressEmbeddable")
     */
   private $address;
} 


<?php 

namespace AppBundle\Embeddable;

/** @Embeddable */
class AddressEmbeddable
{
    /** @Column(type = "string") */
    private $street;

    /** @Column(type = "string") */
    private $postalCode;

    /** @Column(type = "string") */
    private $city;

    /** @Column(type = "string") */
    private $country;
}
```

This way you’ll have again a table dedicated to addresses, but each Address `Entity` will return an Immutable Object, one that returns a new object if edited (IS UP TO YOU TO IMPLEMENT THE `AddressEmbeddable->setNewAddress()` method in such a way it returns a brand new copy of the `AddressEmbeddable` class. See the `Email` example above to better understand this).

[Someone terms “Fake” this kind of Address Entity](http://rosstuck.com/persisting-value-objects-in-doctrine/) that embeds an EmbeddableObject because its unique purpose is to manage an Embeddable.

If seen only in the context of Doctrine, this could also be considered true, but, if considered in the bigger picture of the [Domain Driven Design](https://leanpub.com/ddd-in-php/read), this is the only correct way of doing things.

**The real purpose of a Value Object is to represent an Immutable Value**. The fact that Doctrine calls them Embeddables and treats them in some ways persisting them into the database is something that does not interfere with the real purpose.

So, the `Entity` is a container of values and a value formed by more values has to be a Value Object instead of a simple property.

Using Doctrine, those Value Objects are called Embeddables and are persisted creating columns directly in the table of the `Entity` that embeds.

But the concept of Immutability applied to Value Objects still is valid and has to be used, independently of how the ORMs manage their persisting in the databases.

## Some links to go deeper

- [http://stackoverflow.com/questions/31183954/why-to-use-getter-setters-for-doctrine2-classes](http://stackoverflow.com/questions/31183954/why-to-use-getter-setters-for-doctrine2-classes)
- [http://blog.sznapka.pl/immutable-value-objects-in-php/](http://blog.sznapka.pl/immutable-value-objects-in-php/)
- [http://welcometothebundle.com/price-more-then-money-php-library/](http://welcometothebundle.com/price-more-then-money-php-library/)

About Doctrine and Embeddable/Value Objects:

- [http://welcometothebundle.com/persist-the-money-doctrine-value-object/](http://welcometothebundle.com/persist-the-money-doctrine-value-object/)
- [http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.htm](http://doctrine-orm.readthedocs.org/en/latest/tutorials/embeddables.htm)l
- [http://rosstuck.com/persisting-value-objects-in-doctrine/](http://rosstuck.com/persisting-value-objects-in-doctrine/)
- [http://russellscottwalker.blogspot.it/2013/11/entities-vs-value-objects-and-doctrine-2.html](http://russellscottwalker.blogspot.it/2013/11/entities-vs-value-objects-and-doctrine-2.html)
- [http://stackoverflow.com/questions/7375334/immutable-collections-in-doctrine-2](http://stackoverflow.com/questions/7375334/immutable-collections-in-doctrine-2)

Remember to “Make. Ideas. Happen.”.

I wish you flocking users, see you soon!

L'articolo [Value Objects, Immutable objects and Doctrine Embeddables](https://io.serendipityhq.com/experience/php-and-doctrine-immutable-objects-value-objects-and-embeddables/) proviene da [ÐΞV Experiences by Serendipity HQ](https://io.serendipityhq.com).