PHP moderno: il tipo <strong>readonly</strong> per proprietà e classi

by theArchitect
SHARE
PHP moderno: il tipo <strong>readonly</strong> per proprietà e classi
© Guida-HTML5.it

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

SHARE