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.