readonly în PHP

Clase și obiecte PHP 8.1+ (clase readonly: PHP 8.2+)

O proprietate readonly poate primi valoare o singură dată, apoi nu mai poate fi modificată.

Sintaxă
public readonly tip $proprietate;
readonly class Nume { ... }

Ce face readonly

readonly face o proprietate „doar pentru citire” după ce a primit prima valoare (de obicei în constructor). Orice încercare ulterioară de modificare aruncă eroarea Error. Este ideal pentru obiecte-valoare: o sumă de bani, o adresă, un punct pe hartă.

Proprietățile readonly trebuie să aibă tip. Din PHP 8.2 poți scrie readonly class, iar toate proprietățile devin readonly.

Ca să obții o variantă modificată, creezi un obiect nou. Din PHP 8.5, în interiorul clasei poți scrie clone($this, ["pret" => 70]): copia primește noile valori chiar dacă proprietățile sunt readonly.

Exemple

Exemplul 1: Proprietate readonly

<?php
class Factura
{
    public function __construct(public readonly string $numar, public readonly float $total)
    {
    }
}

$f = new Factura("DEX-0042", 259.9);
echo "$f->numar: $f->total lei\n";

try {
    $f->total = 1;
} catch (Error $e) {
    echo $e->getMessage();
}

Rezultat

DEX-0042: 259.9 lei
Cannot modify readonly property Factura::$total

Exemplul 2: Clasă readonly și copie modificată (PHP 8.5)

<?php
readonly class Pret
{
    public function __construct(public float $valoare, public string $moneda = "lei")
    {
    }

    public function cuReducere(int $procent): static
    {
        return clone($this, ["valoare" => $this->valoare * (100 - $procent) / 100]);
    }
}

$initial = new Pret(200);
$redus = $initial->cuReducere(10);

echo "$initial->valoare $initial->moneda -> $redus->valoare $redus->moneda";

Rezultat

200 lei -> 180 lei

Greșeli frecvente

  • Declari public readonly $x; fără tip. Proprietățile readonly trebuie să aibă tip, altfel primești eroare fatală.
  • Crezi că readonly face tot obiectul „înghețat”. Dacă proprietatea conține alt obiect, acel obiect poate fi modificat în continuare; doar referința nu se poate schimba.

Comenzi înrudite

  • __construct: Constructorul este metoda rulată automat la new. Pregătește obiectul cu datele de pornire.
  • clone: Creează o copie a unui obiect. Fără clone, atribuirea unui obiect copiază doar referința către același obiect.
  • public / private / protected: Stabilește cine are acces la o proprietate sau metodă: oricine (public), doar clasa (private) sau și clasele copil (protected).