Read-only properties in PHP

Posted on Nov 9, 2020

PHP does not yet have support for read only properties, unlike TypeScript, which has the readonly modifier. When working with Value Objects I often find immutability a beneficial characteristic. To implement readonly properties in PHP I have a simple trait that I lean on.

The trait leverages the __get() magic method and PHPdoc property hints for IDE auto-completion. Below is an example class using the trait:

use App\Traits\ReadOnlyProperties;

/**
 * @property-read SheetMaterialSpec $materialSpec
 * @property-read float $length
 * @property-read float $width
 * @property-read int $quantity
 */
class Piece
{
    use ReadOnlyProperties;

    private float $length;
    private float $width;
    private int $quantity;

    public function __construct(float $length, float $width, int $quantity)
    {
        $this->length = $length;
        $this->width = $width;
        $this->quantity = $quantity;
    }
}

And this is trait:

namespace App\Traits;

use InvalidArgumentException;

trait ReadOnlyProperties
{
    public function __get($name)
    {
        if (property_exists($this, $name)) {
            return $this->$name;
        }

        if (isset($this->nullProperties) && in_array($name, $this->nullProperties)) {
            return null;
        }

        throw new InvalidArgumentException("Property $name does not exist on ".static::class);
    }
}

For bonus points, I even have a little unit test to verify the behaviour.

© 2020 Mark Fullbrook — Powered by Statamic and Tailwind