Introduzione
Tra le novità più utili delle versioni recenti di PHP, una delle più pratiche per scrivere codice più sicuro e pulito è l’introduzione delle proprietà readonly. Questa feature è stata pensata per ridurre gli errori legati alla modifica accidentale degli oggetti dopo la loro creazione, un problema molto comune nei progetti medio-grandi.
In parole semplici, una proprietà readonly può essere valorizzata una sola volta, di solito nel costruttore, e poi non può più essere modificata. Questo rende il codice più stabile, più facile da ragionare e spesso anche più adatto a rappresentare dati immutabili, come configurazioni, DTO, identificativi, risultati di query o oggetti dominio.
In questo tutorial vedremo come funziona readonly, quando usarlo davvero, quali vantaggi porta e quali errori evitare. L’obiettivo non è solo conoscere la sintassi, ma capire come integrarla in modo concreto nel tuo stile di sviluppo PHP.
Codice completo
<?php
declare(strict_types=1);
final class UserProfile
{
public readonly int $id;
public readonly string $name;
public readonly string $email;
public readonly DateTimeImmutable $createdAt;
public function __construct(
int $id,
string $name,
string $email,
?DateTimeImmutable $createdAt = null
) {
$this->id = $id;
$this->name = $name;
$this->email = $email;
$this->createdAt = $createdAt ?? new DateTimeImmutable();
}
public function toArray(): array
{
return [
´id´ => $this->id,
´name´ => $this->name,
´email´ => $this->email,
´created_at´ => $this->createdAt->format(DateTimeInterface::ATOM),
];
}
}
// Creazione dell´oggetto
$user = new UserProfile(
id: 10,
name: ´Luca Bianchi´,
email: ´[email protected]´
);
echo $user->toArray()[´name´] . PHP_EOL;
// Tentativo di modifica: genera un errore
// $user->email = ´[email protected]´; Spiegazione
Nel codice sopra abbiamo definito una classe UserProfile con quattro proprietà readonly. Il significato è molto chiaro: una volta creato l’oggetto, quei valori non devono cambiare.
1. Cosa significa readonly
Quando una proprietà è dichiarata con readonly, PHP consente di assegnarle un valore una sola volta. Dopo l’assegnazione iniziale, qualsiasi tentativo di modificarla produce un errore. Questo è utile quando l’oggetto rappresenta un dato che non dovrebbe essere alterato durante il ciclo di vita dell’applicazione.
2. Perché è utile nei progetti reali
- Riduce i bug: nessuno può cambiare per errore un valore fondamentale dell’oggetto.
- Favorisce l’immutabilità: gli oggetti diventano più prevedibili.
- Migliora la leggibilità: il contratto della classe è immediato.
- Aiuta nel debug: se un valore cambia, sai che non può essere avvenuto “silenziosamente” in un altro punto del codice.
3. Assegnazione nel costruttore
Il caso più comune è assegnare le proprietà readonly nel costruttore. In questo modo l’oggetto nasce già completo e coerente. Nel nostro esempio:
- $id identifica in modo univoco il profilo.
- $name e $email contengono i dati principali.
- $createdAt usa un valore di default se non viene passato, grazie a
new DateTimeImmutable().
4. Perché usare DateTimeImmutable
Nel codice abbiamo scelto DateTimeImmutable invece di DateTime. È una scelta coerente con l’approccio readonly: anche la data non può essere modificata “in place”. Se hai bisogno di una data diversa, crei un nuovo oggetto. Questo riduce gli effetti collaterali e rende il comportamento più prevedibile.
5. Cosa succede se provo a modificare la proprietà
La riga commentata:
$user->email = ´[email protected]´; genererebbe un errore, perché email è readonly. Questo è esattamente il comportamento desiderato quando vogliamo proteggere lo stato dell’oggetto.
6. Quando non usarlo
Readonly non è una soluzione universale. Non è adatta a oggetti che devono cambiare frequentemente stato, come entità con lifecycle complesso, carrelli e-commerce, contatori o modelli che vengono aggiornati molte volte durante l’elaborazione. In questi casi, usare readonly in modo forzato può complicare il codice invece di semplificarlo.
Best practice
- Usa readonly per dati stabili: DTO, configurazioni, record di lettura, value object, risultati di API.
- Preferisci classi final quando l’oggetto non deve essere esteso. Questo rende il comportamento ancora più prevedibile.
- Combina readonly con tipi forti: ad esempio
int,string,DateTimeImmutable, array ben strutturati o oggetti dedicati. - Evita di creare oggetti “mezzi pronti”: se un dato è essenziale, passalo nel costruttore.
- Non confondere readonly con immutabilità totale: una proprietà readonly non può essere riassegnata, ma se contiene un oggetto mutabile, quell’oggetto potrebbe comunque cambiare internamente.
Quest’ultimo punto è molto importante. Per esempio, se una proprietà readonly contiene un oggetto DateTime, quell’oggetto può essere modificato con metodi come modify(). Per questo, quando vuoi davvero un comportamento immutabile, spesso è meglio usare classi immutabili come DateTimeImmutable.
Esempio di attenzione con gli oggetti mutabili
<?php
declare(strict_types=1);
final class Event
{
public readonly DateTime $date;
public function __construct(DateTime $date)
{
$this->date = $date;
}
}
$date = new DateTime(´2026-01-01´);
$event = new Event($date);
// Questo modifica l´oggetto DateTime interno
$date->modify(´+1 day´);
echo $event->date->format(´Y-m-d´); // 2026-01-02 In questo esempio la proprietà è readonly, ma il contenuto dell’oggetto non è veramente protetto. È un dettaglio fondamentale da conoscere per evitare false sicurezze.
Riepilogo
Le proprietà readonly sono una delle novità più concrete e utili del PHP moderno. Ti aiutano a scrivere oggetti più chiari, sicuri e facili da mantenere. Sono particolarmente efficaci quando lavori con dati che non devono cambiare dopo la creazione, come profili utente, configurazioni, risultati di elaborazione o oggetti valore.
- Una proprietà readonly si assegna una sola volta.
- È perfetta per dati stabili e oggetti immutabili.
- Aiuta a prevenire bug e modifiche accidentali.
- Non sostituisce una progettazione corretta: va usata con criterio.
- Per vera immutabilità, preferisci anche tipi e oggetti immutabili.
Se stai aggiornando un progetto esistente o iniziando una nuova base di codice in PHP 8.1+, readonly è una feature da conoscere bene e da usare con intelligenza. È un piccolo cambiamento nella sintassi, ma un grande passo avanti nella qualità del design.
Approfondisci con risorse ufficiali
- PHP Manual - Typed Properties: https://www.php.net/manual/en/language.oop5.properties.php
- PHP Manual - Readonly Properties: https://www.php.net/manual/en/language.oop5.properties.php#language.oop5.properties.readonly
- PHP 8.1 Release Notes: https://www.php.net/releases/8.1/en.php
- RFC Readonly Properties 2.0: https://wiki.php.net/rfc/readonly_properties_v2
