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.
Nota:
Quando si sovrascrive un metodo genitore, il metodo del figlio deve corrispondere a qualsiasi dichiarazione del tipo restituito sul genitore. Se il genitore non definisce un tipo restituito, allora il metodo figlio può farlo.
Tipo | Descrizione | Versione |
---|---|---|
Nome 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 array. | |
callable | Il valore deve essere una callable valida. Non può essere utilizzato come dichiarazione del tipo di proprietà della classe. | |
bool | 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 string. | |
iterable |
Il valore deve essere un array o un'instanceof Traversable.
|
PHP 7.1.0 |
object | Il valore deve essere un object. | PHP 7.2.0 |
mixed | Il valore può essere qualsiasi valore. | PHP 8.0.0 |
Gli alias per i tipi scalari di sopra non sono supportati.
Vengono invece trattati come nomi di classi o interfacce.
Ad esempio, usando boolean
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);
?>
Output of the above example in PHP 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 object|resource|array|string|int|float|bool|null. Disponibile a partire da PHP 8.0.0.
Example #1 Dichiarazione 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);
?>
Output of the above example in PHP 8:
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
Example #2 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);
?>
Output of the above example in PHP 8:
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
Example #3 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));
?>
Il precedente esempio visualizzerà:
float(3)
Example #4 Restituzione di un oggetto
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
Il precedente esempio visualizzerà:
object(C)#1 (0) { }
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
.
Example #5 Dichiarazione del tipo di argomento nullable
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>
Il precedente esempio visualizzerà:
object(C)#1 (0) { } NULL
Example #6 Dichiarazione del tipo restituito nullable
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>
Nota:
È possibile ottenere argomenti nullable rendendo
null
il valore predefinito. Questo non è raccomandato in quanto si interrompe durante l'eredità.Example #7 Vecchio modo per rendere gli argomenti nullable
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>Il precedente esempio visualizzerà:
object(C)#1 (0) { } NULL
È possibile combinare tipi semplici in tipi compositi. PHP consente di combinare i tipi nei seguenti modi:
Non è possibile combinare i tipi di intersezione con i 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 T1&T2&...
.
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:
int|string|INT
o
Countable&Traversable&COUNTABLE
generano un errore.
Nota: Ciò non garantisce che il tipo sia “minimo”, poiché ciò richiederebbe il caricamento di tutti i tipi di classe utilizzati.
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)
?>
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.
Nota:
Il ritorno per riferimento da una funzione void è deprecato a partire da PHP 8.1.0, perché tale funzione è contraddittoria. In precedenza, emetteva già il seguente
E_NOTICE
quando chiamata: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à.
Il valore deve essere un'instanceof
della stessa classe di quella
in cui è chiamato il metodo.
Disponibile da PHP 8.0.0.
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.
Le chiamate di funzione dall'interno delle funzioni interne non saranno influenzate
dalla dichiarazione strict_types
.
Per abilitare la modalità rigorosa, il declare
viene utilizzato con la
dichiarazione strict_types
:
Nota:
La tipizzazione strict si applica alle chiamate di funzione effettuate all'interno del file con la tipizzazione strict abilitata, non alle funzioni dichiarate all'interno di quel file. Se un file senza la tipizzazione strict abilitata effettua una chiamata a una funzione che è stata definita in un file con la tipizzazione strict, la preferenza del chiamante (tipizzazione coercitiva) verrà rispettata e il valore verrà forzato.
Nota:
La tipizzazione strict è definita solo per le dichiarazioni di tipo scalare.
Example #8 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));
?>
Output of the above example in PHP 8:
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
Example #9 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));
?>
Il precedente esempio visualizzerà:
int(3) int(3)
Example #10 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));
?>
Il precedente esempio visualizzerà:
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
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:
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.
Nota:
I tipi che non fanno parte dell'elenco di preferenze di cui sopra non sono obiettivi ammissibili per la coercizione implicita. In particolare non si verificano coercizioni implicite ai tipi
null
efalse
.
Example #11 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
?>
Example #12 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);
?>
Output of the above example in PHP 8:
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
Example #13 Cattura TypeError
<?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();
}
?>
Output of the above example in PHP 8:
int(3) Error: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10