Creating Immutable Objects in PHP

First off, as of this writing, PHP doesn’t have built-in immutable objects.

What’s an immutable object? Depends who you talk to. By some definitions, an immutable object is one that cannot have the values of its predefined members changed after instantiation. The following class does not instantiate to an immutable object… it is mutable. Once instantiated, we can use the setter method setBreed to give it a new value.


class Dog { private $breed; public function __construct($breed) { $this->breed = $breed; } public function getBreed() { return $this->breed; } public function setBreed($breed) { $this->breed = $breed; } } $dog = new Dog('Labrador'); $dog->setBreed('Springer Spaniel');

Some people would argue that simply be removing the setter, we make this object immutable:


class Dog { private $breed; public function __construct($breed) { $this->breed = $breed; } public function getBreed() { return $this->breed; } } $dog = new Dog('Labrador'); $dog->breed = 'Spring Spaniel'; // throws error

While removing the setter does protect the $breed property of the object, we can still change the $dog object by adding new properties:

$dog->weight = '22kg';  // this will work
$dog->color = 'black';  // this will work

Assigning or changing values like this takes advantage of the PHP magic method __set() which, unless overridden, is used to set the value of any undefined properties that are assigned after instantiation.

To make this object truly immutable, we’d need to override __set().


class Dog { private $breed; public function __construct($breed) { $this->breed = $breed; } public function getBreed() { return $this->breed; } public function __set($key, $value) { throw new Exception('Cannot change value of immutable object'); } } $dog = new Dog('Labrador'); // works $dog->weight = '22kg'; // throws exception

I’m not really a stickler about immutable objects. If I want it to be immutable, the first approach is generally enough for me. But if you are worried about some renegade function adding properties to your immutable objects in PHP, you might consider overriding __set().