https://a.storyblok.com/f/162428/1280x1262/96ce32308e/group-4-2.png

PHP 8: Novità e Performance nella Versione Migliorativa

Dopo una fase di testing relativamente veloce pare proprio che ci siamo: il 26 Novembre 2020 PHP 8, la nuova major version, sarà disponibile per tutti.

Il termine major version è importante: così come PHP 7 ha introdotto modifiche che hanno rotto le compatibilità con PHP 5.6, dobbiamo aspettarci anche in questo caso un salto tecnologico importante che introdurrà molte breaking changes.

Esattamente come nel passaggio da PHP 5.6 a PHP 7, quindi, la vera differenza la farà la qualità del codice e la capacità del singolo developer di aggiornarsi; utilizzare framework come SymfonyLaravelYii può essere d’aiuto per gestire passaggi di versione così importanti, obbligando lo sviluppatore a scrivere codice il più possibile astratto e di alto livello.

Nuove Funzionalità

Union Types

Link alla RFC

Questa era, personalmente, una delle carenze che più avvertivo nel dichiarare funzioni; il rischio come sempre sarà quello di un abuso della funzionalità; vediamo con un esempio:

public function foo(Foo|Bar $input): int|float;

Prima di PHP 8, l’unica possibilità per ritornare uno o più valori era solo il null, ad esempio con

public function foo(?Foo $input): ?int;

in questo esempio posso ritornare null oppure int e la funzione accetta un $input di tipo null o Foo. Ma cosa succede se il dato di ritorno è, per esempio, un int e un float? Non avrei potuto farlo. Questo non vale se si usa il void: se, quindi, una funzione non ritorna nulla, non mi posso aspettare altri tipi di dato oltre a void (non avrebbe senso dire che il dato di ritorno è int o void).

public function foo(Foo|null $foo): void;

public function bar(?Bar $bar): void;

JIT

Link alla RFC

Il compilatore Just in Time sulla carta promette importanti miglioramenti in termini di performance anche se tutto dipenderà dal caso d’uso specifico. In ambito web, esistono dei benchmark che sembrano sfatare questo mito. Vedremo nei prossimi mesi, soprattutto perché la versione stabile potrebbe essere molto più ottimizzata.

L’operatore nullsafe

Link alla RFC

Alzi la mano chi qualche volta si è trovato l’errore Fatal error: Call to a member function getFoo() on null; questo accade perché magari il codice è scritto così

$object->bar->getFoo();

ma bar è null. L’unica soluzione era quindi quella di usare un operatore ternario (o verificare in due step se bar esiste) ad esempio:

$startDate= $booking->getStartDate();

$dateAsString = $startDate ? $startDate->asDateTimeString() : null;

Se quindi in questo caso esiste $startDate chiamo la funzione asDateTimeString(), altrimenti ritorno null.

In PHP 8 diventa tutto molto più leggibile e pulito

$da

$dateAsString = $booking->getStartDate()?->asDateTimeString();

Quel ? sta facendo esattamente la stessa cosa, ma in modo più veloce e leggibile.

Named arguments

Questa è una grossa novità che sicuramente aiuterà a rendere più leggibile il codice.
Fino ad oggi gli argomenti passati ad una funzione erano posizionali: se quindi il primo elemento era $a e poi $b i valori da passare dovevano seguire questo ordine.

Prendiamo questa struttura:

class CustomerData

{

public function __construct(

public string $name,

public string $email,

public int $age,

) {}

}

Al momento, una volta invocata, l’ordine da seguire è definito dalla firma della funzione; notate la comodità di:

$data = new CustomerData(

age: $input['age'],

name: $input['name'],

email: $input['email'],

);

così facendo non devo ricordarmi la posizione degli elementi ma il loro nome, rendendo tutto molto più leggibile e lineare. Nell’esempio della struttura vedrete la prossima novità di PHP 8, i Constructor property promotion.

Constructor property promotion

Link alla RFC

Una cosa comodissima e che vi eviterà inutili e ripetitive righe di codice.
Si passa da:

class Money

{

public Currency $currency;

public int $amount;

public function __construct(

Currency $currency,

int $amount,

) {

$this->currency = $currency;

$this->amount = $amount;

}

}

a

class Money

{

public function __construct(

public Currency $currency,

public int $amount,

) {}

}

Come potete vedere mi sono evitato la definizione della variabili all’inizio della classe Money così come l’assegnazione nel costruttore.

Match

Premesso che non amo particolarmente gli switch-case in quanto li ritengo, tanto quanto gli else, poco leggibili e funzionali, match permette di avere, in forma compatta, quello che faremmo con uno switch.

Di sicuro avrete visto qualcosa come:

switch ($statusCode) {

case 200:

case 300:

$message = null;

break;

case 400:

$message = 'not found';

break;

case 500:

$message = 'server error';

break;

default:

$message = 'unknown status code';

break;

}

bene, tutto questo si può accorciare in qualcosa di molto più semplice e leggibile:

$message = match ($statusCode) {

200, 300 => null,

400 => 'not found',

500 => 'server error',

default => 'unknown status code',

};

spariscono i break e più valori possono essere accorpati assieme se il risultato è lo stesso. Inoltre ritorna un valore che già viene associato ad una variabile, senza la necessità di ripetere il $message = ogni volta.

Stringhe

Link alla RFC
Link alla RFC

Sono disponibili alcune nuove funzioni in PHP 8, ad esempio str_contains() tornerà true o false senza più dover passare per strpos

if (strpos('string with lots of words', 'words') !== false) { }

diventa

if (str_contains('string with lots of words', 'words')) { }

allo stesso modo abbiamo anche altre due funzioni:

str_starts_with('haystack', 'hay');

str_ends_with('haystack', 'stack');

Trailing comma in parameter lists

Link alla RFC

Quante volte, abituati ad esempio agli array vi siete ritrovati ad aggiungere la virgola all’ultimo parametro di una funzione? Ora finalmente è possibile farlo:

public function(

string $parameterA,

int $parameterB,

Foo $objectfoo,

) {

}

::class per gli oggetti

Link alla RFC

Ultima novità, piccola ma decisamente comoda: al posto di usare get_class() sugli oggetti, si potrà utilizzare il più conosciuto ::class

$foo = new Foo();

var_dump($foo::class);

notate come, finalmente, possa usare ::class su $foo.

Conclusioni

PHP 8 porta sicuramente una ventata di novità e freschezza, obbligando il developer a utilizzare sempre più sintassi simili ad altri linguaggi e abbandonando sempre più concezioni legacy che hanno, negli anni, rovinato la sua reputazione.

Il salto non sarà quindi importante come da PHP 5 a PHP 7 proprio perché un gran lavoro di svecchiamento è stato già fatto.

Tocca ora ai programmatori scrivere del buon codice e utilizzare questi nuovi tools; tutto ciò che in PHP 8 è stato tolto (diventando quindi una breaking change) lo trovate qui, nella guida all’upgrade.

Inutile dire che moltissime di queste funzionalità erano state deprecate in PHP 7, quindi se si sono fatti bene i compiti a casa non dovrebbero esserci problemi.

Ringrazio il sempre aggiornato stitcher.io e Brent per l’ottimo articolo in inglese.


Potrebbe interessarti...
Soluzioni software
Investimenti software: Credito di imposta fino al 2023
Soluzioni software
Docker: lo strumento ideale per programmare
Soluzioni software
Integrazioni hardware: una consulenza a 360 gradi