Post Image

Come le Property Hooks Trasformano il Tuo Codice in PHP 8.4

Nel precedente articolo, Novità PHP 8.4, ti ho parlato delle nuove funzionalità introdotte con la versione 8.4.1 di PHP, rilasciata il 21 novembre 2024. Ora voglio approfondire una di queste novità: le Property Hooks.

Questa caratteristica permette di gestire meglio le proprietà di una classe, rendendo il codice più semplice e veloce da scrivere. Inoltre, avvicina PHP a linguaggi come Python, grazie a una sintassi più moderna e intuitiva.

Prima di PHP 8.4: Come funzionavano Getter e Setter?

In PHP, quando avevi bisogno di controllare come una proprietà di una classe veniva letta o modificata, usavi i metodi getter e setter. Questi metodi servono per proteggere le proprietà dichiarate come private (cioè non direttamente accessibili dall'esterno della classe).

Ecco un esempio di come si faceva prima:

class Locale
{
    private string $languageCode;
    private string $countryCode;

    public function __construct(string $languageCode, string $countryCode)
    {
        $this->setLanguageCode($languageCode);
        $this->setCountryCode($countryCode);
    }

    public function getLanguageCode(): string
    {
        return $this->languageCode;
    }

    public function setLanguageCode(string $languageCode): void
    {
        $this->languageCode = $languageCode;
    }

    public function getCountryCode(): string
    {
        return $this->countryCode;
    }

    public function setCountryCode(string $countryCode): void
    {
        $this->countryCode = strtoupper($countryCode);
    }

    public function setCombinedCode(string $combinedCode): void
    {
        [$languageCode, $countryCode] = explode('_', $combinedCode, 2);
        $this->setLanguageCode($languageCode);
        $this->setCountryCode($countryCode);
    }

    public function getCombinedCode(): string
    {
        return \sprintf("%s_%s", $this->languageCode, $this->countryCode);
    }
}

Come vedi, ci sono molti metodi, anche per fare cose semplici come leggere o modificare una proprietà. Questo crea alcuni problemi:

  • Molto codice superfluo: Molti metodi sono quasi identici.
  • Manutenzione più complicata: Se decidi di cambiare qualcosa, devi modificare più punti nel codice.
  • Poca chiarezza: Per capire come funziona una proprietà, devi cercare il getter o il setter corrispondente.
  • Accesso indiretto: Le proprietà non sono direttamente accessibili, costringendo gli sviluppatori a interfacciarsi sempre attraverso i metodi dedicati.

PHP 8.4: Cosa sono le Property Hooks?

Con le Property Hooks, puoi definire direttamente come una proprietà deve comportarsi quando viene letta (get) o modificata (set). Non serve più scrivere tanti metodi separati, tutto è incluso nella definizione della proprietà stessa.

Ecco lo stesso esempio riscritto usando le Property Hooks:

class Locale
{
    public string $languageCode;

    public string $countryCode
    {
        set (string $value) {
            $this->countryCode = strtoupper($value);
        }
    }

    public string $combinedCode
    {
        get => \sprintf("%s_%s", $this->languageCode, $this->countryCode);
        set (string $value) {
            [$this->languageCode, $this->countryCode] = explode('_', $value, 2);
        }
    }
}

Questo nuovo approccio offre diversi vantaggi:

  • Sintassi Concisa: Getter e setter vengono definiti direttamente all'interno della dichiarazione delle proprietà, eliminando la necessità di metodi separati.

  • Maggiore leggibilità: Il codice risulta più chiaro e lineare, consentendo di vedere subito le regole di accesso e modifica delle proprietà.

  • Performance migliorate: L'accesso diretto alle proprietà, anziché passare per metodi dedicati, rende il codice più performante in situazioni di uso intensivo.

  • Accessibilità diretta: Le proprietà possono essere lette e scritte con una sintassi semplice e naturale:

    $brazilianPortuguese->countryCode; // Accesso diretto alla proprietà
    

Il hook get

Il hook get controlla cosa succede quando leggi una proprietà. Ad esempio:

class Persona
{
    public string $nomeCompleto {
        get {
            return $this->nome . ' ' . $this->cognome;
        }
    }

    public function __construct(
        public string $nome,
        public string $cognome
    ) {}
}

$persona = new Persona('Mario', 'Rossi');
echo $persona->nomeCompleto; // Mario Rossi

In questo caso ogni volta che accediamo il metodo nomeCompleto della classe Persona avremo la concatenazione del nome e del cognome divisi da spazio.

Compatibilità del Tipo

Il tipo del valore restituito dal hook get deve corrispondere al tipo dichiarato per la proprietà. Se i tipi non corrispondono, PHP tenterà di convertire automaticamente il valore, a meno che i tipi stretti (strict types) siano abilitati. Se i tipi stretti sono abilitati, è necessario assicurarsi che il valore restituito corrisponda esattamente al tipo della proprietà, altrimenti verrà generato un errore.

Il hook set

Il hook set controlla cosa accade quando modifichi una proprietà. Ecco un esempio:

class Persona
{
    public string $nome {
        set(string $value) {
            $this->nome = strtoupper($value);
        }
    }

    public function __construct(string $nome)
    {
        $this->nome = $nome;
    }
}

$persona = new Persona('mario');
echo $persona->nome; // MARIO

Nell'esempio, il set garantisce che qualsiasi nome assegnato a una classe Persona venga memorizzato in lettere maiuscole

Compatibilità del Tipo

Similmente al hook get, il tipo del valore passato al hook set deve essere compatibile con il tipo della proprietà. Se i tipi non corrispondono, PHP genererà un errore se i tipi stretti (strict types) sono abilitati.

Proprietà di classe write-only e read-only

Con i property hook, puoi creare proprietà che sono solo scrivibili o solo leggibili.

  • write-only(Sola scrittura): Puoi assegnare un valore ma non leggerlo. Questo avviene quando definisci un hook set ma non un hook get.
  • read-only(Sola lettura): Puoi leggere il valore ma non assegnarlo. Questo avviene quando definisci un hook get ma non un hook set.

Esempi di proprietà in Sola Scrittura (write-only)

Ecco un esempio in cui puoi impostare una password ma non leggerla:

class Utente
{
    public string $password {
        set(string $valore) {
            $this->hashedPassword = password_hash($valore, PASSWORD_DEFAULT);
        }
    }

    private string $hashedPassword;
}

$utente = new Utente();
$utente->password = 'segreto';
// echo $utente->password; // Errore: impossibile accedere a una proprietà sola scrittura

Esempi di proprietà in Sola Lettura (read-only)

Ecco un esempio in cui puoi leggere un valore calcolato ma non impostarlo direttamente:

class Cerchio
{
    public float $raggio;

    public float $area {
        get {
            return pi() * $this->raggio ** 2;
        }
    }

    public function __construct(float $raggio)
    {
        $this->raggio = $raggio;
    }
}

$cerchio = new Cerchio(5);
echo $cerchio->area; // 78.5398...
// $cerchio->area = 100; // Errore: impossibile impostare una proprietà sola lettura

Cose da Tenere a Mente Quando Si Usano i Property Hook

Quando lavori con i property hook in PHP, ci sono alcuni punti importanti da considerare:

  • Solo per le Proprietà degli Oggetti: I property hook possono essere applicati solo alle proprietà degli oggetti, non a quelle statiche. Se una proprietà è statica, non può avere un hook.

  • Comportamento Sovrascritto: I property hook sovrascrivono qualsiasi comportamento predefinito per la lettura o scrittura di una proprietà. La logica personalizzata nei hook controllerà come la proprietà viene accessibile o modificata.

  • Accesso a Metodi e Proprietà: I property hook possono accedere a tutti i metodi e proprietà dell’oggetto, siano essi pubblici, privati o protetti. Questo include anche le proprietà che potrebbero avere i loro hook.

  • No ai Riferimenti: Non puoi impostare riferimenti su proprietà con hook. Questo perché modificare un valore tramite riferimento bypasserebbe l’hook set definito per la proprietà.

  • Ereditarietà e Ridefinizione degli Hook: In una classe figlia, puoi ridefinire singoli hook per una proprietà ridefinendo solo gli hook che desideri cambiare. Il tipo e la visibilità della proprietà seguono le loro regole, e ogni hook può sovrascrivere indipendentemente l’implementazione della classe genitore.

Conclusioni

Le Property Hooks rendono il codice più semplice, leggibile e sicuro. Ora puoi controllare ogni aspetto delle tue proprietà direttamente nella classe. Inizia a usarle e scoprirai quanto è più facile lavorare con PHP!