L’introduzione dell’operatore null coalescing con PHP 7 è stato un buon passo avanti per la pulizia del codice, ma non ha portato miglioramenti per quanto riguarda i metodi di classe, perché su di essi non era possibile utilizzarlo. Per aggirare il problema eravamo costretti ad assegnare il risultato del metodo e poi controllarlo prima di utilizzarlo, in questo modo:

$data = $intervento->getStartDate();

$data_string = $data ? $intervento->asDateTimeString() : null;

PHP 8 ha visto l’introduzione del null-safe operator, considerabile come una funzionalità simile al null-coalescing ma applicata appunto a questo tipo di operazioni.

$country = null;

if ($session !== null) {
    $user = $session->user;

    if ($user !== null) {

    $address = $user->getAddress();

    if ($address !== null) {
        $country = $address->country;
        }
    }
}

PHP 8 ci permette di scrivere questo blocco di controllo IF in questo modo:

$country = $session?->user?->getAddress()?->country;

Vediamolo in dettaglio.

L’operatore nullsafe nel dettaglio

Siccome potrebbe confondere, la prima domanda alla quale risponderemo è: qual è la differenza tra questo nuovo operatore e il null-coalescing, che continua ovviamente ad esistere?

Partiamo da questo esempio:

class Ordine
{
    public ?Fattura $fattura = null;
}

$ordine = new Ordine();

In questa situazione, la proprietà $fattura della classe Ordine è collegata ad un istanza della classe Fattura, che può esserci o non esserci (un ordine può avere una fattura collegata, o magari ancora no). Difatti, utilizziamo la notazione ? davanti al tipo di dato al momento della dichiarazione. Come sappiamo, questo ci dice che $fattura può essere soltanto di tipo Fattura o di tipo null.

Se accedessimo direttamente ad una proprietà di $fattura, utilizzando ad esempio $ordine->fattura->numero, otterremmo un errore, come in questo caso:

echo $ordine->fattura->numero;

// errore, $order->fattura è null, non possiamo accedere alla proprietà "numero"

Con il null-safe operator potremmo scrivere, senza incorrere in errore:

echo $order->fattura?->numero;

Abbiamo visto come utilizzare il null-safe operator sulle proprietà, possiamo utilizzarlo naturalmente anche sui metodi:

class Ordine
{
    public static function getReferral(): ?User
    {
        // ...
    }
}

Possiamo utilizzare l’operatore per assicurarci che il risultato di getReferral() sia null:

echo Ordine::getReferral()?->cognome;

Analogamente a quanto visto nel caso precedente, il metodo getReferral() potrebbe restituire null oppure una istanza di Utente. Se provassimo quindi ad accedere alla proprietà cognome di Utente potremmo incorrere in errore:

echo (Ordine::getReferral()->cognome ?? 'nessun cognome');

Fatal error: Uncaught Error: Call to a member function getReferral() on null

Operatori annidati

È possibile utilizzare operatori multipli, come in questo caso:

$classe?->metodo1()?->metodo2()?->metodo3();

In questo caso metodo1() verrà chiamato solo se $classe non è null, metodo2() solo se metodo1() non è null e così via.

Per concludere, questo nuovo operatore introdotto in PHP 8 era un pezzo decisamente mancante, e semplificherà sicuramente la scrittura e la leggibilità del codice.