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.