Novità delle ultime minor di PHP 8.x

Maico Orazio
weBeetle
Published in
14 min readAug 2, 2023

Ogni volta che viene rilasciata una nuova versione di PHP siamo entusiasti perché di solito porta nuove e interessanti funzionalità e miglioramenti delle prestazioni.

Ed è esattamente quello che è successo con PHP 8.1, rilasciato il 25 novembre 2021, PHP 8.2, rilasciato l’8 dicembre 2022 e quello che sarà di PHP 8.3, che verrà rilasciato il 23 novembre 2023.

Di seguito alcune delle principali novità della prima minor 8.1, rilasciata un anno dopo la prima pubblicazione del ramo 8.

Enums

RFC https://wiki.php.net/rfc/enumerations

Definisce un tipo personalizzato che è limitato ad uno o un numero discreto di possibili valori.

Sono tipi speciali, un tipo di classe che ha oggetti a singola istanza. Possono essere impiegati ovunque, dove è possibile utilizzare gli oggetti.

Vediamo la sintassi: sono identificati dalla parola chiave enum che precede il nome, proprio come le classi, e il suo corpo è costituito da case.

enum UserStatus 
{
case Active;
case Pending;
case Deleted;
}
$active = UserStatus::Active;
var_dump($active); // enum(UserStatus::Active)

Enum è molto simile ad una classe e i case sono simili a costanti di una istanza della classe. Quindi possiamo pensare a $active come una istanza della classe UserStatus.

Possiamo recuperare il nome:

var_dump($active->name); // string(6) "Active"
print_r($active); // UserStatus Enum { [name] => Active }

I valori enum sono rappresentati internamente da oggetti, ma è possibile assegnare loro un valore. Ogni case può avere il suo valore corrispondente.

enum UserStatus: int 
{
case Active = 1;
case Pending = 2;
case Deleted = 3;
}
$active = UserStatus::Active;
print_r($active); // UserStatus Enum { [name] => Active [value] => 1 }
echo $active->name; // Active
echo $active->value; // 1

Sono consentiti solo valori numerici o stringhe. Se si decide di specificare un valore all’ enum, è necessario inizializzare tutti i case con un valore.

Esiste un metodo from() che restituisce il relativo enum del valore indicato.

$statusDb = 1;
$enumStatus = UserStatus::from($statusDb);
var_dump($enumStatus); // enum(UserStatus::Active)

Otteniamo un errore se indichiamo un valore non specificato nell’ enum.

$statusDb = 4;
$enumStatus = UserStatus::from($statusDb);
// Fatal error: Uncaught ValueError: 4 is not a valid backing value for enum “UserStatus” …

Esiste un secondo metodo tryFrom() che cerca di creare un enum dal valore dato in input, e restituisce null se viene passato un valore sconosciuto.

$statusDb = 4;
$enumStatus = UserStatus::tryFrom($statusDb);
var_dump($enumStatus); // NULL

In questo ultimo caso possiamo utilizzare l’operatore di coalescenza nullo per assegnare un valore di default:

$statusDb = 4;
$enumStatus = UserStatus::tryFrom($statusDb) ?? UserStatus::Pending;
var_dump($enumStatus); // enum(UserStatus::Pending)

Metodi di enumerazione

Gli enum possono avere anche dei metodi, proprio come le classi. Questa è una funzionalità molto potente, soprattutto in combinazione con l’operatore match.

// è possibile implementare interfacce
interface MyInterface {
public function hello();
public static function staticHelloInterface();
}

enum UserStatus: int implements MyInterface
{
case Active = 1;
case Pending = 2;
case Deleted = 3;

public function text(): string {
return match ($this) {
self::Active => 'User is active',
self::Pending => 'User is pending',
self::Deleted => 'User is deleted',
default => null,
};
}

// Puo' avere anche metodi statici
public static function staticMethod(): string {
return "Hello from static";
}

// metodi da implementare dell'interfaccia MyInterface
public function hello(): string {
return "hello interface";
}

public static function staticHelloInterface(): string {
return "hello static interface";
}
}

var_dump(UserStatus::Active->text()); // "User is active"
var_dump(UserStatus::Pending->hello()); // "hello interface"
var_dump(UserStatus::staticMethod()); // "Hello from static"
var_dump(UserStatus::staticHelloInterface()); // "hello static interface"

Possono avere anche delle costanti che possono essere di tipo primitivo (int, string, boolean) oppure fare riferimento ad un case.

public cost ARCHIVED = self::Deleted;

Se abbiamo bisogno dell’elenco di tutti i case dell’ enum, possiamo utilizzare il metodo cases().

var_dump(UserStatus::cases()); // [ [0]=>enum(UserStatus::Active), [1]=>enum(UserStatus::Pending) [2]=>enum(UserStatus::Deleted) ]

Proprietà di sola lettura

RFC https://wiki.php.net/rfc/readonly_properties_v2

In PHP 8.1 è possibile dichiarare una proprietà di classe come di sola lettura.

Le proprietà di sola lettura non possono essere modificate dopo l’inizializzazione, ovvero dopo che è stato loro assegnato un valore; il tentativo di modificare una proprietà di sola lettura, genererà un errore.

class Order {
public function __construct(
public readonly string $user,
public float $amount
)
{}
}

$order = new Order('Maico', 100);
var_dump($order); // object(Order)#1 (2) { ["user"]=>string(4) "Maico", ["amount"]=>float(100) }

$order->user = 'Giuseppe';
var_dump($order); // Fatal error: Uncaught Error: Cannot modify readonly property Order::$user …

Dichiarando una proprietà readonly non possiamo inizializzarla nella dichiarazione, possiamo farlo nel costruttore. A meno che non usiamo la sintassi del Constructor Property Promotion:

class Order 
{
public function __construct(
public readonly string $user = 'Maico Orazio',
public float $amount;
)
{}
}

Il motivo per cui è consentito è perché il valore predefinito di una proprietà promossa non viene utilizzato come valore predefinito per la proprietà della classe, ma solo per l’argomento del costruttore.

class Order 
{
public readonly string $user;

public function __construct(
string $user = 'Maico Orazio',
public float $amount;
)
{
$this->user = $user;
}
}

Le proprietà di sola lettura possono essere utilizzate solo in combinazione con le proprietà tipizzate; puoi comunque utilizzare mixed come suggerimento di tipo. PHP imposterà automaticamente il valore null se non viene fornito alcun valore esplicito nel costruttore.

Intersezioni di tipi

RFC https://wiki.php.net/rfc/pure-intersection-types

Se con PHP 8.0 è stato introdotto la possibilità di unire i tipi, in PHP 8.1 è possibile effettuare una intersezione di tipi con il simbolo &.

Dove l’unione di tipi richiede che l’input sia uno dei tipi specificati, l’intersezione di tipi richiede che l’input sia tutti i tipi specificati.

Al momento non è possibile combinare intersezione e unione di tipi A&B|C.

Fibers

RFC https://wiki.php.net/rfc/fibers

PHP 8.1 aggiunge il supporto per le Fibers che consentono l’esecuzione di codice simultaneo in PHP. La fiber è un blocco di codice che contiene il proprio stack di variabili e stati. Possono essere considerate come thread applicativi e possono essere avviate dal programma principale.

Una volta avviata, il programma principale non sarà in grado di sospenderla o terminarla, ma ciò è possibile solo dall’interno del blocco di codice della fiber. Dopo che è stata sospesa, il controllo torna al programma principale che può riprendere l’esecuzione della fiber dal punto in cui era stata sospesa:

$fiber = new Fiber(function(): void {
echo "Welcome to Fiber\n";
Fiber::suspend();
echo "Welcome back to Fiber\n";
});
echo "Starting a Fiber\n";
$fiber->start();
echo "Fiber has been suspended\n";
echo "Resuming the Fiber\n";
$fiber->resume();
echo "Fiber completed execution\n";

output:

Starting a Fiber
Welcome to Fiber
Fiber has been suspended
Resuming the Fiber
Welcome back to Fiber
Fiber completed execution

Nuova funzione array_is_list

RFC https://wiki.php.net/rfc/is_list

Con questa nuova funzione è possibile verificare rapidamente se un array sia una lista.

La funzione array_is_list() controlla se le chiavi di un array siano in ordine sequenziale a partire da 0, siano tutti interi e senza salti intermedi. Se tutte le condizioni sono soddisfatte, restituisce true.

Ecco alcuni esempi:

// validi
array_is_list([]); // true
array_is_list([1, 2, 3]); // true
array_is_list(['cats', 2, 3]); // true
array_is_list(['cats', 'dogs']); // true
array_is_list([0 => 'cats', 'dogs']); // true
array_is_list([0 => 'cats', 1 => 'dogs']); // true

// NO validi
array_is_list([1 => 'cats', 'dogs']); // as first key isn't 0
array_is_list([1 => 'cats', 0 => 'dogs']); // keys are out of order
array_is_list([0 => 'cats', 'bark' => 'dogs']); // non-integer keys
array_is_list([0 => 'cats', 2 => 'dogs']); // gap in between keys

Definire costanti di classe final

RFC https://wiki.php.net/rfc/final_class_const

A partire da PHP 8.0, è possibile sovrascrivere le costanti di classe con le sottoclassi. Ciò è dovuto al modo in cui l’ereditarietà è implementata in PHP.

In PHP 8.1 possiamo dichiarare costanti di classe finali tramite il modificatore final se vogliamo che la costante non sia sovrascritta nelle classi figlie. Nel caso viene generato un fatal error.

class Math 
{
final public const PI = 3.14;
}

class SubClass extends Math
{
public const PI = 3;
}
echo SubClass::PI; // Fatal Error

final non può essere utilizzato per le costanti private, perché non è possibile accedervi al di fuori della classe.

new negli inizializzatori

RFC https://wiki.php.net/rfc/new_in_initializers

PHP supporta l’impostazione dei valori iniziali direttamente nell’elenco dei parametri, ma solo per i tipi primitivi.

Con PHP 8.1 siamo in grado di utilizzare la stessa sintassi del ‘valore predefinito’ anche per gli oggetti. In altre parole, ora è consentito utilizzare la parola chiave new nelle definizioni delle funzioni, variabili statiche e costanti globali, nonché negli argomenti di attributo.

class Service 
{
private Logger $logger;
function public __construct(?Logger $logger = null)
{
$this->logger ??= new NullLogger();
}
}

// PHP 8.1
class Service
{
public function __construct(
private Logger $logger = new NullLogger()
)
{}
}

Funzioni fsync e fdatasync

RFC https://wiki.php.net/rfc/fsync_function

PHP 8.1 aggiunge due nuove funzioni di file system chiamate fsync e fdatasync, entrambe utili per svuotare il buffer della memoria fisica. Novità attesa da tempo.

La funzione fsync() è simile alla funzione esistente fflush(), ma differisce per il fatto che mentre fflush() esegue il flush dei buffer interni dell’applicazione verso il sistemo operativo, fsync() fa sì che i buffer interni vengano eseguiti sulla memoria fisica. Questo assicura una scrittura completa e persistente che permette di recuperare i dati anche dopo un crash dell’applicazione o del sistema. Tutte le altre esecuzioni di codice sono bloccate fino alla fine della scrittura.

La funzione fdatasync() va utilizzata per sincronizzare i dati ma non necessariamente i metadati, rendendo la scrittura un po’ più veloce, perché tecnicamente sono due scritture su disco.

Nuova chiave full_path in $_FILES per i caricamenti di directory

PHP 8.1 aggiunge il supporto per una nuova chiave full_path nella variabile globale $_FILES. Prima di PHP 8.1, $_FILES non memorizzava i percorsi relativi o la directory esatta sul server, per questo motivo non era possibile caricare un’intera directory utilizzando il modulo HTML di caricamento file.

Questa nuova chiave full_path risolve il problema, memorizzando i percorsi relativi e ricostruendo l’esatta struttura delle directory sul server, rendendo possibile il caricamento dell’intera directory:

<php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
var_dump($_FILES);
}
?>
<form action="" method="POST" enctype="multipart/form-data">
<input name="myfiles[]" type="file" webkitdirectory multiple />
<button type="submit">Submit</button>
</form>

output:

array(1) {
["myfiles"]=> array(6) {
["name"]=> array(2) {
[0]=> string(9) "image.png"
[1]=> string(9) "image.png"
}
["full_path"]=> array(2) {
[0]=> string(25) "folder1/folder2/image.png"
[1]=> string(25) "folder3/folder4/image.png"
}
["tmp_name"]=> array(2) {
[0]=> string(14) "/tmp/phpV1J3EM"
[1]=> string(14) "/tmp/phpzBmAkT"
}
// … + error, type, size
}
}

Il tipo restituito never

RFC https://wiki.php.net/rfc/noreturn_type

PHP 8.1 aggiunge il supporto per un nuovo tipo restituito chiamato never. Questo tipo può essere utilizzato per indicare che una funzione non ritornerà un valore e terminerà l’esecuzione dello script, attraverso le funzioni exit() o die() o generando un’eccezione.

Il tipo never è simile al tipo restituito void, tuttavia quest’ultimo continua l’esecuzione. L’obiettivo di never è di applicare una funzione che impedisce l’esecuzione del resto del codice:

class Route 
{
public function __construct()
{
}
public static function redirect($url, $httpCode = 301): never
{
header(“Location: {$url}”, true, $httpCode);
die;
}
}
Route::redirect('https://webeetle.com');
echo "hello";

Argomenti con nomi dopo la decompressione

In PHP 8.1 possiamo combinare insieme argomenti con nome e decompressione degli argomenti.

function sum($a, $b, $c) 
{
echo $a + $b + $c;
}
$numbers = [1, 2];
sum(...$numbers, c: 3); // 6

Decompressione degli array per gli array con chiave a stringa

RFC https://wiki.php.net/rfc/array_unpacking_string_keys

PHP 7.4 ha aggiunto il supporto alla decompressione degli array tramite l’operatore spread. Tuttavia, questa caratteristica era limitata agli array con chiave numerica.

PHP 8 ha aggiunto il supporto degli argomenti con nome, rimuovendo questa limitazione. Quindi, con PHP 8.1 abbiamo la possibilità di decomprimere gli array con chiavi di tipo stringa con la stessa sintassi.

$array1 = ['a' => 1];
$array2 = ['b' => 2];
$result = ['a' => 0, ...$array1, ...$array2];
var_dump($result); // Array['a' => 1, 'b' => 2];

PHP 8.1 è un importante aggiornamento del linguaggio PHP. In questo articolo abbiamo visto alcune delle nuove funzionalità, ma introduce ulteriori miglioramenti delle prestazioni e altro ancora (https://www.php.net/manual/en/migration81.php).

Andiamo alla successiva minor PHP 8.2, dove le caratteristiche più interessanti sono i nuovi tipi standalone, le classi di sola lettura e, ovviamente, i numerosi miglioramenti delle prestazioni.

Come per la precedente versione, esploriamo alcune delle novità introdotte da PHP 8.2.

Classi di sola lettura

RFC https://wiki.php.net/rfc/readonly_classes

Come abbiamo riportato sopra, PHP 8.1 ha introdotto la possibilità di dichiarare readonly le proprietà delle classi; ora PHP 8.2 aggiunge il supporto alla dichiarazione dell’intera classe come di sola lettura.

Se dichiariamo una classe come readonly, tutte le sue proprietà saranno automaticamente di sola lettura, senza la necessità di specificarlo.

Se con PHP 8.1 dobbiamo scrivere il seguente codice per dichiarare tutte le proprietà della classe come readonly :

class User 
{
public readonly string $firstname;
public readonly string $lastname;
public readonly string $username;
public readonly string $email;
public readonly string $gender;
}

Ora, con PHP 8.2, è necessario dichiarare readonly la sola classe:

readonly class User 
{
public string $firstname;
public string $lastname;
public string $username;
public string $email;
public string $gender;
}

E’ possibile dichiarare readonly anche le classi astratte e finali.

abstract readonly class ClassExampleAbstract {}
final readonly class ClassExampleFinal {}

Vale la stessa regola per le proprietà di sola lettura; una classe dichiarata readonly può contenere solo proprietà tipizzate o mixed , nel caso verrà generato un errore fatale.

readonly class User 
{
public $firstname;
public string $lastname;
public string $username;
public string $email;
public string $gender;
}
Fatal error: Readonly property User::$firstname must have type in /in/h1Krv on line 5

true, false e null come tipi autonomi

RFC https://wiki.php.net/rfc/null-false-standalone-types https://wiki.php.net/rfc/true-type

PHP 8.0 ha introdotto l’unione tra i tipi, primitivi e anche di classi, e la stessa RFC consentiva anche l’uso di false e null , ma non erano ammessi come tipi a sé stanti.

Ora con PHP 8.2 possiamo dichiarare ancora con più precisione i tipi di ritorno, di parametro e di proprietà; inoltre aggiunge il supporto anche per il tipo true.

Entrambi i tipi true e false sono essenzialmente un tipo di unione del tipo primitivo bool ; per evitare la ridondanza, è errato dichiararli come unione di tipi.

Fatal error: Type contains both true and false, bool should be used instead ...

Tipi di Disjunctive Normal Form (DNF)

RFC https://wiki.php.net/rfc/dnf_types

La Disjunctive Normal Form è un modo standard per strutturare le espressioni booleane in una serie di OR di AND.

In PHP 8.2 è stato applicato alle dichiarazioni di tipo, nello specifico per scrivere tipi di unione e intersezione combinati, in modo che il parser possa gestirli.

I tipi DNF consentirebbero dichiarazioni di tipo per proprietà, parametri e valori restituiti nella seguente forma:

// Accetta un oggetto che implementa sia A che B, 
// OR un oggetto che implementa D.
(A&B)|D

// Accetta un oggetto che implementa C,
// OR un figlio di X che implementa anche D,
// OR nullo.
C|(X&D)|null

// Accetta un oggetto che implementa tutti e tre A, B e D,
// OR un int,
// OR null.
(A&B&D)|int|null

Ecco alcuni esempi di casi non validi per la forma DNF e come potrebbero essere riscritti:

A&(B|D) 
// riscritto come (A&B)|(A&D)

A|(B&(D|W)|null)
// riscritto come A|(B&D)|(B&W)|null

Ridurre i parametri sensibili nei back-traces

RFC https://wiki.php.net/rfc/redact_parameters_in_back_traces

Come qualsiasi linguaggio di programmazione, PHP permette di tracciare lo stack delle chiamate in qualsiasi punto dell’esecuzione del codice.

Alcune di queste tracce dello stack di PHP possono rappresentare un inconveniente, includere informazioni sensibili come nome utente, password e variabili d’ambiente.

PHP 8.2 consente di contrassegnare tali parametri sensibili con il nuovo attributo \SensitiveParameter escludendolo nel back-traces:

function example (
$username,
$firstname,
$lastname,
#[\SensitiveParameter]$gender
)
{
throw new \Exception('Error');
}

example('mainick', 'Maico', 'Orazio', 'male');

/*
Fatal error: Uncaught Exception: Error in /in/3NeKK:10
Stack trace:
#0 /in/3NeKK(13): example('mainick', 'Maico', 'Orazio', Object(SensitiveParameterValue))
#1 {main}
thrown in /in/3NeKK on line 10

Process exited with code 255.
*/

Qualsiasi parametro con l’attributo \SensitiveParameter verrà sostituito con un oggetto \SensitiveParameterValue e il suo valore reale non verrà mai registrato nel trace.

Nuova funzione mysqli_executive_query e metodo mysqli::executive_query

RFC https://wiki.php.net/rfc/mysqli_execute_query

PHP 8.2 rende più semplice l’esecuzione di query MySQLi parametrizzate grazie alla nuova funzione mysqli_executive_query($query, $params) e al metodo mysqli::executive_query.

Questa nuova funzione è una combinazione delle funzioni mysqli_prepare(), mysqli_executive() e mysql_stmt_get_result() : la query viene preparata, vincolata (se si passano i parametri) ed eseguita all’interno della funzione stessa. Se la query viene eseguita correttamente, restituirà un oggetto mysqli_result, altrimenti false.

Costanti nei Traits

RFC https://wiki.php.net/rfc/constants_in_traits

Attualmente, i Traits permettono di definire solo metodi e proprietà, ma non le costanti. PHP 8.2 consente la definizione anche delle costanti, proprio come quelle di una classe.

trait Foo 
{
public const FLAG_1 = 1;
protected const FLAG_2 = 2;
private const FLAG_3 = 2;

public function doFoo(int $flags): void
{
if ($flags & self::FLAG_1) {
echo 'Got flag 1';
}
if ($flags & self::FLAG_2) {
echo 'Got flag 2';
}
if ($flags & self::FLAG_3) {
echo 'Got flag 3';
}
}
}

Terminiamo l’articolo esaminando alcune delle RFC accettate finora e che saranno introdotte da PHP 8.3.

Emendamenti di sola lettura

RFC https://wiki.php.net/rfc/readonly_amendments

Come abbiamo riportato sopra, le proprietà di sola lettura, introdotte in PHP 8.1, non possono essere modificate dopo l’inizializzazione. Questa RFC propone due modifiche, al momento solo una è stata accettata: la possibilità di reinizializzare le proprietà di sola lettura durante la clonazione.

Si potrebbe pensare che con la semplice clonazione sia ora possibile escludere il vincolo. In realtà la RFC consente la sovrascrittura dei valori di sola lettura solo nel metodo magico __clone().

class Order {
public function __construct(
public readonly string $user,
public float $amount;
)
{}

public function __clone()
{
$this->user = 'Francesco';
}
}

Questa RFC consente di clonare anche gli oggetti nidificati e sovrascriverli nel metodo magico.

class Order {
public function __construct(
public readonly string $user,
public float $amount,
public DateTime $createdAt
)
{}

public function __clone()
{
$this->user = 'Francesco';
$this->createdAt = clone $this->createdAt;
}
}

Senza questo RFC, la clonazione dell’oggetto Order manterrebbe comunque un riferimento all'oggetto originale $createdAt. Supponendo di modificare quell'oggetto, il che è possibile poiché readonlyimpedisce solo la modifica della proprietà assegnata, non la modifica dei suoi valori interni:

$order = new Order(/* … */);
$otherOrder = clone $order;
$order->createdAt->add(new DateInterval('P1D'));
$otherOrder->createdAt === $order->createdAt; // true

Ci ritroveremmo con la data createdAt modificata su entrambi gli oggetti.

Grazie a questa RFC, possiamo creare cloni reali, con tutte le loro proprietà nidificate clonate, anche quando queste sono di sola lettura.

La nuova funzione json_validate

RFC https://wiki.php.net/rfc/json_validate

Attualmente, l’unico modo per verificare se una stringa è un JSON valido comporta decodificarla json_decode e rilevare se vengono generati errori json_last_error. Con PHP 8.3 potremmo utilizzare la nuova funzione json_validate() che sarà utile nel caso in cui abbiamo bisogno di sapere se l'input è un JSON valido. Inoltre, secondo la sua RFC, consuma anche meno risorse.

json_validate(string $json, int $depth = 512, int $flags = 0): bool

Recupero dinamico delle costanti di una classe

RFC https://wiki.php.net/rfc/dynamic_class_constant_fetch

Questa RFC propone di consentire l’accesso dinamico alle costanti di classe utilizzando le variabili.

class Foo 
{
public const FLAG_1 = 1;
protected const FLAG_2 = 2;
private const FLAG_3 = 2;
}

$name = 'FLAG_';
foreach ([1,2,3] as $idx)
{
constant(Foo::class . '::' . $name.$idx);
Foo::{$name.$idx};
}

Invece di accedere alle costanti di classe con un valore di stringa statico Foo::FLAG_1, è possibile utilizzare una variabile contenente il nome della costante.

Migliore gestione degli errori in unserialize

RFC https://wiki.php.net/rfc/improve_unserialize_error_handling

Questa proposta mira a migliorare la gestione degli errori nella funzione unserialize(), che è incoerente e difficile da gestire in modo affidabile.

A seconda della stringa di input, le versioni di PHP precedenti alla 8.3 emettono un E_NOTICE, un E_WARNINGo generano un'eccezione arbitraria o un errore fatale; rendendo difficile la gestione degli errori che si verificano durante l’annullamento della serializzazione.

La soluzione proposta si compone di due parti:

  • Aggiungere una nuova eccezione UnserializationFailedException, consentendo di utilizzare un blocco catch per esso e gestire tutti i possibili errori durante il processo;
  • Aumentare la severità della segnalazione degli errori nel parser unserialize() in modo che tutti i casi emettano E_WARNINGo generino la nuova eccezione UnserializationFailedException.

Costanti di classe tipizzate

RFC https://wiki.php.net/rfc/typed_class_constants

Le costanti di classe tipizzate possono essere dichiarate in classi, interfacce, tratti ed enum. Supporteranno tutte le dichiarazioni di tipo PHP tranne void, callable e never. Le costanti di classe sono covarianti, il che significa che i loro tipi non possono ampliarsi durante l’ereditarietà. Devono corrispondere al tipo della costante di classe, con l’eccezione che le costanti di classe float possono accettare anche valori interi.

interface Foo 
{
public const string FLAG_1 = 'first';
public const float FLAG_2 = 2.2;
}

class Bar extends Foo {
// Non è possibile modificare il tipo
// e assegnare un valore di un altro tipo.
// public const array FLAG_1 = ['foo', 'bar', 'baz'];
// OK.
public const string FLAG_1 = 'second';
public const string FLAG_2 = 2;
}

Quale preferite delle nuove funzionalità descritte sopra? Condividete le vostre considerazioni nella sezione dei commenti.

Buon lavoro 👨‍💻

--

--

Maico Orazio
weBeetle

Senior Web Application Developer. I'm a software engineer, a passionate coder, and a web developer. I am a fan of technology. #php #symfony #javascript #reactjs