Dopo una fase di testing relativamente veloce pare proprio che ci siamo: il 26 Novembre 2020, la nuova major version PHP 8, il linguaggio di programmazione più noto per lo sviluppo di server, sarà disponibile per tutti.
Scopriamo insieme, nel prossimo articolo, le principali novità e performance della nuova versione di questo linguaggio.
Il passaggio da PHP 7 a PHP 8
Creato dallo sviluppatore Rasmus Lerdorf venticinque anni fa per la creazione di pagine web dinamiche, PHP è il linguaggio di programmazione più noto per lo sviluppo di server, che nel tempo si è evoluto in un linguaggio completo e professionale, grazie anche al supporto della community e di professionisti che ruota intorno ad esso.
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, la vera differenza la farà la qualità del codice e la capacità del singolo developer di aggiornarsi; utilizzare framework come Symfony, Laravel, Yii 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.
La principale novità di PHP 8: JIT
Principale novità di questa versione è il supporto per la compilazione JIT (Just-in-Time), il cui compito è quello di migliorare la performance, interpretando e compilando le parti del codice riga per riga durante il runtime, ovvero l’esecuzione. In termini pratici quindi il JIT è una modalità di compilazione durante il funzionamento stesso di una applicazione e per questo parliamo di “traduzione dinamica”, perché avviene durante l’esecuzione anziché prima.
Le fasi di esecuzione di PHP 8 con OPcache
La procedura di esecuzione di PHP 8 si compone di quattro fasi:
- Lexing/Tokenizing per la costruzione di un set di token.
- Parsing tramite l’uso di token, per costruire l’AST, ovvero la rappresentazione gerarchica del codice sorgente.
- Compilation: l’interprete traduce i nodi AST in Zend opcode di basso livello, che determinano il tipo di istruzione eseguita dalla Zend VM.
- Interpretation: gli opcode vengono interpretati ed eseguiti sulla Zend VM.
L’abilitazione di OPcache permette di velocizzare le operazioni e di ottimizzare le prestazioni macchina avendo dei contenuti immediati senza attendere. In altre parole, con OPcache l’interprete PHP attraversa le quattro fasi della procedura solo la prima volta in cui viene eseguito lo script, rendendo immediatamente disponibili i bytecode della rappresentazione intermedia di basso livello per eseguirli poi sulla Zend VM.
Le caratteristiche principali di PHP 8
La versione PHP 8 si è infatti allineata alla robustezza dei sistemi legacy più blasonati, mantenendo però le caratteristiche esclusive che lo rendono un metodo sicuro:
- Strutturato: la nuova release è caratterizzata dalla tipizzazione, comportando maggiori controllo e stabilità sulla piattaforma.
- Performante: sicuro per la prestazione e il controllo in fase di sviluppo, build e deploy.
- Standardizzato: maggiore coerenza nelle risposte da parte delle funzioni di sistema.
In DotEnv il team sviluppo lavora già con PHP 7.4, rilasciata lo scorso novembre, per poter garantire una sempre migliore performance. Con il rilascio della nuova versione quindi aggiorneremo ulteriormente metodi e procedure, certi dei vantaggi che PHP8 comporterà, dopo il rilascio della versione Beta1 lo scorso 6 agosto.
Le nuove funzionalità di PHP 8
Union Types
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
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
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
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
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
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
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
.
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.
Ora sta agli sviluppatori scrivere del buon codice e utilizzare questi nuovi tools; tutto ciò che in PHP 8 è stato tolto (diventando quindi una breaking change) lo trovate nella guida all’upgrade.
Fonte: stitcher.io e Brent
In DotEnv le competenze in termini di linguaggi di programmazione non mancano. Gli sviluppatori sono un gruppo eterogeneo che seguono procedure precise per raggiungere precisi obiettivi e rilasciare software performanti ai clienti.