Scopri cosa c’è di nuovo e cosa è cambiato nella nuova versione di PHP 8.
Il tanto atteso rilascio di PHP 8.0 è stato effettuato il 26 novembre 2020 e si tratta di un importante aggiornamento e una mile stone notevole, poiché apporta diverse nuove funzionalità al sistema di digitazione, alla sintassi, alla gestione degli errori, alle stringhe, alla programmazione orientata agli oggetti e altro ancora.
Sono gli sforzi di centinaia di persone che si uniscono per plasmare il futuro di un linguaggio di programmazione che alimenta una parte significativa dei siti Web e delle applicazioni Internet.
PHP 8.0 cerca di essere conservatore con le modifiche che possono rompere la maggior parte delle applicazioni, eppure porta diverse nuove funzionalità principali.
Funzionalità come Named Parameters, JIT, Attributes e Constructor Properties apportano importanti miglioramenti e modifiche alla sintassi, mentre diversi miglioramenti minori come le migrazioni da risorse a oggetti, una migliore gestione degli errori e modifiche e miglioramenti negli operatori e nei confronti del motore aiutano a ridurre le possibilità di bug.
Nuove funzionalità principali
Parametri denominati
PHP 8.0 consente parametri con nome nelle chiamate di funzioni / metodi oltre ai tradizionali parametri posizionali.
str_contains(needle: 'Bar', haystack: 'Foobar');
Questo rende i nomi dei parametri di funzione / metodo parte dell’API pubblica. Il DocBlock @ no-named-arguments non standardizzato esprime che la libreria non fornisce compatibilità con le versioni precedenti per i parametri denominati.
Attributi
Gli attributi consentono di dichiarare metadati per funzioni, classi, proprietà e parametri. Gli attributi vengono mappati ai nomi delle classi PHP (dichiarati con un attributo stesso) e possono essere recuperati in modo programmatico con PHP Reflection API.
#[CustomAttribute]
class Foo {
#[AnotherAttribute(42)]
public function bar(): void {}
}
Gli attributi rendono facile ed efficiente dichiarare attributi / annotazioni che in precedenza richiedevano di memorizzarli nei commenti di DocBlock e analizzare la stringa per dedurli.
Proprietà Constructor
Una nuova sintassi per dichiarare le proprietà della classe direttamente dal costructor della classe (metodo magico __construct).
class User {
public function __construct(private string $name) {}
}
Nel costructor, PHP 8.0 supporta la dichiarazione della visibilità (pubblica, privata o protetta) e del tipo. Tali proprietà verranno registrate come proprietà di classe con la stessa visibilità e tipo con cui sono dichiarate nel costruttore.
Questa funzionalità incompatibile con le versioni precedenti può aiutare a ridurre il codice boilerplate quando si dichiarano classi di oggetti valore.
Compilazione just-in-time
PHP Opcache supporta JIT. È disabilitato per impostazione predefinita e, se abilitato, JIT compila e memorizza nella cache le istruzioni native. Non fa una differenza notevole nelle applicazioni Web associate a IO, ma fornisce un aumento delle prestazioni per le applicazioni pesanti per la CPU.
# Enabling JIT in php.ini
opcache.enable=1
opcache.jit_buffer_size=100M
opcache.jit=tracing
Nota che JIT è ancora nuovo e ha avuto correzioni di bug fino a un giorno prima del rilascio di PHP 8.0.0. Rende il debug e la creazione di profili più difficili con il livello aggiuntivo aggiunto.
Union Types
Gli Union Types estendono le dichiarazioni di tipo (tipi restituiti, parametri e proprietà di classe) per dichiarare più di un tipo.
function parse_value(string|int|float): string|null {}
Supporta anche false come tipo speciale (per booleano false), una caratteristica prevalente nel codice legacy che non utilizzava le eccezioni.
Operatore Null-safe
L’operatore Null-safe fornisce sicurezza nel concatenamento di metodi / proprietà quando il valore o la proprietà restituiti può essere null.
return $user->getAddress()?->getCountry()?->isoCode;
L’operatore ?-> null-safe mette in cortocircuito il resto dell’espressione se incontra un valore null e restituisce immediatamente null senza causare alcun errore.
Espressioni match
Le espressioni match sono simili ai blocchi switch, ma i blocchi di corrispondenza forniscono confronti indipendenti dai tipi, supportano un valore restituito, non richiedono la suddivisione delle istruzioni break e supportano più valori corrispondenti. Garantisce inoltre che almeno un ramo sia abbinato, assicurando che tutti i casi siano presi in considerazione.
$response = match('test') {
'test' => $this->sendTestAlert(),
'send' => $this->sendNuclearAlert(),
};
Non tutti i blocchi switch potrebbero convertirsi bene in blocchi match. Il codice che richiede compatibilità con le versioni precedenti, switch blocchi con più istruzioni (al contrario di espressioni a riga singola) o si aspetta che la funzionalità fall-through si adatti ancora alle istruzioni switch.
WeakMaps
Una WeakMap consente di memorizzare e associare valori arbitrari per le chiavi dell’oggetto, ma senza impedire al garbage collector di cancellare l’oggetto se è è fuori dall’ambito in qualsiasi altro luogo.
Una WeakMap è simile a SplObjectStorage, poiché sia WeakMap che splObjectStorage utilizzano objectss come chiave e consente l’archiviazione di valori arbitrari. Tuttavia, una WeakMap non impedisce che l’oggetto venga sottoposto a Garbage Collection.
Miglioramenti del sistema di digitazione
PHP 8.0 migliora il sistema di digitazione con l’aggiunta di Union Types e il tipo misto.
Union Types
Gii Union Types estendono le dichiarazioni di tipo (tipi restituiti, parametri e proprietà di classe) per dichiarare più di un tipo.
function parse_value(string|int|float): string|null {}
Supporta anche false come tipo speciale (per booleano false), una caratteristica prevalente nel codice legacy che non utilizzava le eccezioni.
Nuovo mixed pseudo type
PHP 8.0 porta il mixed pseudo type, che era già ampiamente utilizzato nei commenti di DocBlock.
function dd(mixed $var): void {
var_dump($var);
}
il mixed pseudo type può essere utilizzato per indicare che accetta qualsiasi tipo o può restituire qualsiasi tipo. In un contesto di classe / interfaccia, il tipo misto riproduce le stesse regole del principio di sostituzione di Liskov.
Static return type, per metodi di classe
Il static return type, già supportato come tipo restituito DocBlock, è ora supportato in PHP 8.0. Il tipo restituito statico dichiara che verrà restituito un oggetto della classe chiamata.
class Foo {
public static function getInstance(): static {
return new static();
}
}
Miglioramenti alla gestione degli errori
Un cambiamento importante e incompatibile con le versioni precedenti in PHP è che le funzioni interne ora generano eccezioni su errori di tipo o errori di valore.
Ciò corregge il comportamento storico di PHP di emettere un avviso e restituire null quando incontra un valore che non può utilizzare. Questo comportamento è spesso indesiderato perché gli avvisi PHP non interrompono l’esecuzione del blocco rimanente.
Gli avvisi delle funzioni interne ora generano eccezioni TypeError e ValueError
Quasi la totalità delle funzioni interne di PHP ora impone il controllo del tipo e, invece degli avvisi, PHP ora genera eccezioni TypeError o ValueError. Sulla base del codice legacy, questa modifica può causare problemi, ora che gli errori sono gestiti in modo più audace e imperdonabile.
Espressioni throw in
Prima di PHP 8.0, non era possibile generare eccezioni da un’espressione (ad esempio un’istruzione ternaria). Questo è ora consentito in PHP 8.0.
$value = isset($_GET['value'])
? $_GET['value']
: throw new \InvalidArgumentException('value not set');
Le eccezioni catch solo per tipo
È possibile eseguire il catch delle eccezioni in base al loro tipo, senza catturare l’oggetto eccezione.
try {}
catch(TypeError) {
// Did not catch the $exception object
}
La segnalazione degli errori di default è impostata su E_ALL
La configurazione predefinita di PHP 8.0 mostra tutti i messaggi di errore per impostazione predefinita. È stato configurato per nascondere deprecazioni e avvisi rigorosi nelle versioni precedenti.
Gli errori di avvio di PHP vengono visualizzati per impostazione predefinita
PHP ora visualizza gli errori di avvio (errore nel caricare estensioni dinamiche, configurazioni INI non valide, ecc.) Per impostazione predefinita.
Le asserzioni generano eccezioni per impostazione predefinita
Le asserzioni PHP (assert ()) ora generano eccezioni sugli errori di asserzione. Prima di PHP 8.0, richiedeva una configurazione esplicita disabilitata per impostazione predefinita.
@ L’operatore di soppressione degli errori non tacita gli errori irreversibili
PHP 8.0 corregge il comportamento dell’operatore di soppressione degli errori @, dove tacita gli errori irreversibili, che portano a un errore di script, perché l’operatore @ non previene gli errori irreversibili, ma piuttosto nasconde la visualizzazione del messaggio di errore.
Modifiche alla programmazione orientata agli oggetti PHP
PHP 8.0 è la prima versione ad essere rigorosa sulle violazioni del principio di sostituzione di Liskov. Prima di PHP 8.0, PHP non era coerente su come gestiva le firme dei metodi incompatibili.
In PHP 8.0, tutte le mancate corrispondenze di firme, inclusi i tratti astratti, si traducono in un errore fatale. Inoltre, applica le firme per i metodi magic.
Errori irreversibili su firme di metodi incompatibili
PHP 8.0 genera errori fatali quando il principio di sostituzione di Liskov non viene seguito quando le classi vengono estese o le interfacce vengono implementate.
Prima di PHP 8.0, le firme incompatibili emettevano solo un avviso.
class Foo {
public function process(stdClass $item): array{}
}
class SuperFoo extends Foo{
public function process(array $items): array{}
// ^^^^^ mismatch
}
Fatal error: Declaration of SuperFoo::process(array $items): array must be compatible with Foo::process(stdClass $item): array in ... on line ...
Le firme dei metodi di classe magic vengono applicate rigorosamente
Da PHP 8.0 e versioni successive, i metodi magic (ad esempio __toString (), __get (), ecc.), Se dichiarano i tipi, devono implementare la firma che PHP si aspetta. Questo per evitare la minima possibilità che l’utente dichiari un metodo magic che non segue il significato semantico.
class Foo {
public function __toString(): object {
}
}
Dichiarazioni come Foo :: __ toString (): object era consentito nelle versioni precedenti di PHP, ma PHP 8.0 e genera un’eccezione se la firma non soddisfa i requisiti.
La chiamata a metodi di classe non statici produce staticamente un errore irreversibile
PHP 8.0 non consente più di chiamare metodi di classe come metodo statico.
class Foo {
public function bar() {}
}
Foo::bar();
Le regole di ereditarietà non vengono applicate ai metodi delle classi private
PHP 8.0 riduce l’applicazione di flag di firma, astratta e statica per i metodi delle classi private. Questo cambiamento deriva dalla logica secondo cui i metodi privati sono proprio questo: Privati.
Da PHP 8.0, ora è consentito alle classi figlie di dichiarare metodi astratti e modificare static / flags per metodi privati.
:: La costante magic di classe è ora supportata sugli oggetti
La costante magic :: restituisce il nome completo della classe. Questo era consentito solo sui nomi delle classi (come Foo \ Bar :: class), ma in PHP 8.0, la costante magic :: class funziona anche sugli oggetti istanziati.
Modifiche relative alle stringhe
In PHP 8.0, ci sono diversi piccoli cambiamenti che potrebbero non essere ovvi all’inizio, ma possono portare a risultati abbastanza inaspettati.
Una delle principali differenze in PHP 8.0 è che, PHP ora considera che ci sia una stringa vuota tra ogni carattere in una determinata stringa.
Prima di PHP 8.0, il controllo di una stringa vuota (“”) non era consentito, ma in PHP 8.0, PHP lo accetterà volentieri e restituirà che c’è effettivamente una stringa vuota tra ogni carattere.
La gestione multibyte o funzioni come strlen restituisce ancora gli stessi valori delle versioni precedenti, ma vengono modificate tutte le funzioni che controllano una sottostringa in una determinata stringa.
Inoltre, PHP 8.0 cambia il modo in cui l’operatore di concatenazione di stringhe ha priorità e supporta nuovi modificatori nelle funzioni sprintf come i modificatori% he% H e * il modificatore di larghezza e precisione.
substr, iconv_substr, grapheme_substr restituiscono una stringa vuota su offset fuori limite
Queste funzioni bloccano i parametri ago e offset alla lunghezza della stringa e restituiscono una stringa vuota invece di restituire false.
substr('FooBar', 42, 3); // "" in PHP >=8.0, false in PHP < 8.0
mb_substr('FooBar', 42, 3); // "" in PHP >=8.0, false in PHP < 8.0
iconv_substr('FooBar', 42, 3); // "" in PHP >=8.0, false in PHP < 8.0
grapheme_substr('FooBar', 42, 3); // "" in PHP >=8.0, false in PHP < 8.0
Gli operatori +/- hanno la precedenza maggiore se usati con l’operatore concat (.)
Quando gli operatori matematici + e – vengono utilizzati nella stessa espressione con l’operatore di concatenazione (.), Gli operatori + e – hanno la precedenza maggiore. Ciò ha comportato un avviso di deprecazione nelle versioni PHP precedenti alla 8.0, ma ora avviene silenziosamente e come da avviso.
echo 35 + 7 . '.' . 0 + 5;
// 42.5 in PHP >= 8.0
// 47 in PHP <= 8.0
Float indipendente dalle impostazioni locali per il casting di stringhe
Quando un valore float viene convertito in stringa, PHP non utilizza più la locale. Prima di PHP 8.0, PHP considerava la locale corrente (che non è thread-safe) o la locale di sistema quando lo faceva. Ciò ha comportato output di stringhe incoerenti perché alcune impostazioni locali, specialmente quelle europee, scambiano il separatore delle migliaia e il segno decimale dalle impostazioni internazionali degli Stati Uniti.
Per il cast di una stringa da float sensibile alle impostazioni locali, è possibile utilizzare il modificatore% f nella classe di funzioni printf.
Inoltre, i nuovi modificatori% he% H per la classe di funzioni printf forniscono varianti indipendenti dalla locale dei modificatori% ge% G.