Readonly properties e readonly classes in PHP 8.1/8.2
Immutabilità, clone con override, readonly su constructor promotion
Un oggetto che rappresenta un fatto già accaduto: un ordine confermato, una fattura emessa, una coordinata geografica. Non dovrebbe più poter cambiare dopo essere stato creato. Prima di PHP 8.1, imporre questa regola richiedeva disciplina personale (getter senza setter, convenzioni). Con readonly, diventa il motore PHP stesso a farla rispettare.
Nella vita reale: è la differenza tra una ricevuta fiscale stampata e uno scontrino che puoi ancora modificare con una penna. La ricevuta, una volta emessa, è definita: nessuno, nemmeno chi l'ha stampata, può più alterarla senza che risulti un'evidente manomissione.
1. readonly properties: una sola scrittura, poi mai più
Una proprietà readonly può essere impostata solo una volta, e solo da dentro la classe stessa (nel costruttore o in un altro metodo). Dopo quella prima scrittura, ogni tentativo di modifica, anche dentro la classe, genera un errore.
class Utente
{
public readonly int $id;
public function __construct(int $id)
{
$this->id = $id; // OK: prima (e unica) assegnazione
}
}
$u = new Utente(42);
echo $u->id; // 42 -- lettura sempre permessa
$u->id = 43; // Error: Cannot modify readonly property Utente::$id
Fonte: PHP Manual — «Properties»: le proprietà readonly possono essere inizializzate una sola volta e solo dallo scope della classe dichiarante.
2. readonly si combina con la constructor promotion
La proprietà readonly funziona anche sui parametri promossi nel costruttore — la sintassi vista nella pillola sulla property promotion — rendendo un DTO immutabile in una sola riga per campo, senza dover scrivere dichiarazione e assegnazione separate.
class Coordinata
{
public function __construct(
public readonly float $lat,
public readonly float $lng,
) {
}
}
$roma = new Coordinata(41.9, 12.5);
$roma->lat = 0;
// Error: Cannot modify readonly property Coordinata::$lat
3. Il tranello del clone: perché non basta clonare per modificare
Ecco l'insidia più comune per chi arriva da poco a readonly: clonare un oggetto non resetta le sue proprietà a «non inizializzate». Il valore era già stato scritto, quindi anche sulla copia clonata resta bloccato.
$originale = new Coordinata(41.9, 12.5);
$copia = clone $originale;
$copia->lat = 45.0;
// Error: la proprieta' era gia' inizializzata, resta bloccata
Da PHP 8.3, il manuale registra un'apertura: le proprietà readonly possono essere reinizializzate, ma solo dentro un metodo magico __clone() scritto appositamente, non da fuori la classe.
class Coordinata
{
public function __construct(
public readonly float $lat,
public readonly float $lng,
) {
}
public function conNuovaLat(float $lat): static
{
$clone = clone $this;
// Dentro __clone(), su PHP 8.3+, si può reinizializzare:
$clone->lat = $lat;
return $clone;
}
}
Pensiamo a fotocopiare un documento firmato: la fotocopia non diventa magicamente un modulo bianco da riempire: riporta la stessa firma, e per cambiarla serve rifare la procedura ufficiale da capo, non scarabocchiarci sopra.
4. readonly class (PHP 8.2): tutte le proprietà, in un colpo solo
Scrivere readonly davanti a ogni proprietà di un DTO con molti campi è ripetitivo. Da PHP 8.2, marcare l'intera classe come readonly equivale a dichiarare public readonly su ciascuna proprietà, automaticamente.
readonly class Prodotto
{
public function __construct(
public string $nome,
public float $prezzo,
public string $categoria,
) {
}
}
// Equivalente a scrivere "public readonly" su ciascun parametro
Due vincoli dall'RFC ufficiale: tutte le proprietà devono essere tipizzate (niente proprietà senza tipo), e una classe readonly può estendere solo un'altra classe readonly, mai una classe normale, e viceversa.
In sintesi
| Regola | Cosa significa | Da PHP |
|---|---|---|
| readonly $prop | Una sola scrittura, poi immutabile | 8.1 |
| readonly su promotion | Immutabile già nel costruttore, senza righe extra | 8.1 |
| clone + readonly | La copia eredita il blocco: serve __clone() per cambiare | 8.3 |
| readonly class | Tutte le proprietà readonly in automatico | 8.2 |
Il filo conduttore è uno solo: l'immutabilità non è più una promessa mantenuta a mano, ma una garanzia che il motore PHP fa rispettare al posto tuo, perfetta per value object, DTO e qualunque dato che rappresenti un fatto già accaduto.
Commenti (0)
Registrati per commentare, fare domande e proporre l'argomento della prossima pillola (oppure accedi se hai già un account).
Nessun commento. Sii il primo a scrivere qualcosa.