Le dichiarazioni di tipo possono essere aggiunte agli argomenti delle funzioni, ai valori restituiti e, a partire da PHP 7.4.0, alle proprietà di classe. Assicurano che il valore sia del tipo specificato al momento della chiamata, altrimenti viene generato un TypeError.
Tipi singoli
TypeDescriptionVersionNome di classe/interfaccia Il valore deve essere un'Instanceof della classe o dell'interfaccia data. self Il valore deve essere un'Instanceof della stessa classe di quella in cui viene utilizzata la dichiarazione del tipo. Può essere utilizzato solo nelle classi. parent Il valore deve essere un'Instanceof del genitore della classe in cui viene utilizzata la dichiarazione del tipo. Può essere utilizzato solo nelle classi. array Il valore deve essere un . arraycallable Il valore deve essere una valida. Non può essere utilizzato come dichiarazione del tipo di proprietà della classe. callablebool Il valore deve essere un valore booleano. float Il valore deve essere un numero in virgola mobile. int Il valore deve essere un numero intero. string Il valore deve essere una . stringiterable Il valore deve essere un o un'Instanceof . arrayTraversablePHP 7.1.0object Il valore deve essere un . objectPHP 7.2.0mixed Il valore può essere qualsiasi valore. PHP 8.0.0boolean come dichiarazione di tipo
richiederà che il valore sia un Instanceof della classe o dell'interfaccia
boolean, invece che di tipo bool:
<?php
function test(boolean $param) {}
test(true);
?>
Example outputs 8
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
Stack trace:
#0 -(3): test(true)
#1 {main}
thrown in - on line 2
mixed è equivalente al tipo union objectresourcearraystring intfloatboolnull . Disponibile a partire da PHP 8.0.0.
EsempiDichiarazione di base del tipo classe
<?php
class C {}
class D extends C {}
// Questa non estende C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
C
D
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
Stack trace:
#0 -(14): f(Object(E))
#1 {main}
thrown in - on line 8
Dichiarazione di base del tipo interfaccia
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// Questa non implementa I.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
C
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
Stack trace:
#0 -(13): f(Object(E))
#1 {main}
thrown in - on line 8
Dichiarazione di base del tipo restituito
<?php
function sum($a, $b): float {
return $a + $b;
}
// Notare che verrà restituito un float.
var_dump(sum(1, 2));
?>
float(3)
Restituzione di un oggetto
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
object(C)#1 (0) {
}
Tipo nullable
A partire da PHP 7.1.0, le dichiarazioni di tipo possono essere contrassegnate come nullable anteponendo al
nome del tipo un punto interrogativo (?).
Ciò significa che il valore può essere del tipo specificato o null.
Dichiarazione del tipo di argomento nullable <?php class C {} function f(?C $c) { var_dump($c); } f(new C); f(null); ?> Example outputs object(C)#1 (0) { } NULL Dichiarazione del tipo restituito nullable <?php function get_item(): ?string { if (isset($_GET['item'])) { return $_GET['item']; } else { return null; } } ?>
null il valore predefinito.
Questo non è raccomandato in quanto si interrompe durante l'eredità.
Vecchio modo per rendere gli argomenti nullable
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>
Example outputs
object(C)#1 (0) {
}
NULL
Tipi compositi
È possibile combinare tipi semplici in tipi compositi. PHP consente di combinare i tipi nei seguenti modi:
- Union di tipi semplici. A partire da PHP 8.0.0.
- Intersezione di tipi di classi (interfacce e nomi di classi). A partire da PHP 8.1.0.
Non è possibile combinare i tipi di intersezione con i tipi union.
Tipi union
Una dichiarazione di tipo union accetta valori di più tipi semplici diversi,
anziché uno solo.
I tipi union vengono specificati utilizzando la sintassi T1|T2|....
I tipi union sono disponibili a partire da PHP 8.0.0.
Il tipo null è supportato come parte delle union,
in modo tale che T1|T2|null possa essere utilizzato per creare una union nullable.
La notazione ?T esistente è considerata una scorciatoia
per il caso comune di T|null.
null non può essere utilizzato come tipo autonomo.
Il tipo letterale false è supportato come parte delle union
ed è incluso poiché per ragioni storiche molte funzioni interne restituiscono
false invece di null per gli errori.
Un classico esempio di tale funzione è strpos.
false non può essere utilizzato come tipo autonomo (incluso
il tipo autonomo nullable).
Pertanto, false, false|null
e ?false non sono consentiti.
Il tipo letterale true non
esiste.
Una dichiarazione di tipo intersezione accetta valori che soddisfano più
dichiarazioni di tipo classe, anziché una singola.
I tipi intersezione sono specificati utilizzando la sintassi T1AmpT2Amp....
I tipi intersezione sono disponibili a partire da PHP 8.1.0.
Per rilevare semplici bug nelle dichiarazioni di tipo composito, i tipi ridondanti che
possono essere rilevati senza eseguire il caricamento della classe risulteranno in un
errore in fase di compilazione. Ciò comprende:
Ogni tipo risolto dal nome può verificarsi solo una volta. Tipi come
int|string|INT o
CountableAmpTraversableAmpCOUNTABLE
generano un errore.
L'utilizzo di mixed genera un errore.
Per i tipi union:
Se viene usato bool, false non può essere utilizzato in aggiunta.
Se viene usato object, i tipi di classe non possono essere utilizzati in aggiunta.
Se viene usato iterable, array
e Traversable non possono essere utilizzati in aggiunta.
Per i tipi intersezione:
L'utilizzo di un tipo che non è un tipo di classe genera un errore.
L'utilizzo di self, parent o
static genera un errore.
Ad esempio, se A e B sono alias di
classe, A|B rimane un tipo di union legale, anche
se potrebbe essere ridotto a A o
B.
Allo stesso modo, se la classe B extends A {}, anche A|B
è un tipo di union legale, anche se potrebbe essere ridotta solo a
A.
<?php
function foo(): int|INT {} // Non consentito
function foo(): bool|false {} // Non consentito
function foo(): int&Traversable {} // Non consentito
function foo(): self&Traversable {} // Non consentito
use A as B;
function foo(): A|B {} // Non consentito ("use" fa parte della risoluzione dei nomi)
function foo(): A&B {} // Non consentito ("use" fa parte della risoluzione dei nomi)
class_alias('X', 'Y');
function foo(): X|Y {} // Consentito (la ridondanza è nota solo in fase di esecuzione)
function foo(): X&Y {} // Consentito (la ridondanza è nota solo in fase di esecuzione)
?>
Tipi di solo ritorno
void
void è un tipo di ritorno che indica che la funzione non
restituisce un valore.
Pertanto non può essere parte di una dichiarazione di tipo union.
Disponibile da PHP 7.1.0.
Only variable references should be returned by reference.
<?php
function &test(): void {}
?>
never è un tipo di ritorno che indica che la funzione non
ha un ritorno. Ciò significa che chiama exit, genera
un'eccezione o è un ciclo infinito.
Pertanto non può essere parte di una dichiarazione di tipo union.
Disponibile a partire da PHP 8.1.0.
never è, nel gergo della teoria dei tipi, il tipo inferiore. Significa che è il sottotipo di ogni altro tipo e può sostituire qualsiasi altro tipo di ritorno durante l'ereditarietà.
staticIl valore deve essere un'Instanceof della stessa classe di quella in cui è chiamato il metodo. Disponibile da PHP 8.0.0.
Tipizzazione strict
Per impostazione predefinita, PHP costringerà i valori del tipo sbagliato nella dichiarazione del tipo scalare previsto, se possibile. Ad esempio, una funzione a cui viene assegnato un int per un parametro che prevede una string otterrà una variabile di tipo string.
È possibile abilitare la modalità strict per file. In modalità strict, sarà accettato solo un valore corrispondente esattamente alla dichiarazione del tipo, altrimenti verrà lanciato un TypeError. L'unica eccezione a questa regola è che un valore int passerà una dichiarazione di tipo float.
strict_types.
Per abilitare la modalità rigorosa, il Declare viene utilizzato con la
dichiarazione strict_types:
Tipizzazione strict per i valori degli argomenti
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>
int(3)
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
Stack trace:
#0 -(9): sum(1.5, 2.5)
#1 {main}
thrown in - on line 4
Tipizzazione coercitiva per i valori degli argomenti
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// Questi verranno convertiti in numeri interi: nota l'output qui sotto!
var_dump(sum(1.5, 2.5));
?>
int(3)
int(3)
Tipizzazione strict per i valori di ritorno
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
int(3)
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
Stack trace:
#0 -(9): sum(1, 2.5)
#1 {main}
thrown in - on line 5
Tipizzazione coercitiva con tipi union
Quando strict_types non è abilitato, le dichiarazioni di tipo scalare
sono soggette a limitate coercizioni di tipo implicito.
Se il tipo esatto del valore non fa parte della union, il tipo di destinazione
viene scelto nel seguente ordine di preferenza:
int
float
string
bool
Se il tipo esiste nella union e il valore può essere forzato al
tipo sotto la semantica di controllo del tipo esistente di PHP, viene scelto il tipo.
Altrimenti viene provato il tipo successivo.
In via eccezionale, se il valore è una stringa e sia int che float fanno parte
della union, il tipo preferito è determinato dalla semantica
“stringa numerica” esistente.
Ad esempio, per "42" viene scelto int,
mentre per "42.0" viene scelto float.
null e false.
Esempio di tipi che vengono forzati in un tipo parte della union
<?php
// int|string
42 --> 42 // tipo esatto
"42" --> "42" // tipo esatto
new ObjectWithToString --> "Risultato di __toString()"
// oggetto mai compatibile con int, ripiega su string
42.0 --> 42 // float compatibile con int
42.1 --> 42 // float compatibile con int
1e100 --> "1.0E+100" // float troppo grande per il tipo int, ripiega su string
INF --> "INF" // float troppo grande per il tipo int, ripiega su string
true --> 1 // bool compatibile con int
[] --> TypeError // array non compatibile con int o string
// int|float|bool
"45" --> 45 // stringa numerica intera
"45.0" --> 45.0 // stringa numerica float
"45X" --> true // non una stringa numerica, ripiega su bool
"" --> false // non una stringa numerica, ripiega su bool
"X" --> true // non una stringa numerica, ripiega su bool
[] --> TypeError // array non compatibile con int, float o bool
?>
Misc
Parametri passati per referenza Tipizzati
I tipi dichiarati di parametri di referenza vengono controllati all'immissione della funzione, ma non quando la funzione ritorna, quindi dopo che la funzione ritorna, il tipo dell'argomento potrebbe essere cambiato.
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
Stack trace:
#0 -(9): array_baz(1)
#1 {main}
thrown in - on line 2
Cattura
<?php
declare(strict_types=1);
function sum(int $a, int $b) {
return $a + $b;
}
try {
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
} catch (TypeError $e) {
echo 'Error: ', $e->getMessage();
}
?>
int(3)
Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10