Déclarations de type
Les déclarations de types peuvent être ajoutées aux arguments des fonctions, valeurs de retour, et, à partir de PHP 7.4.0, les propriétés de classes. Elles assurent que les valeurs sont du type spécifié au temps de l'appel, sinon une TypeError est lancée.
Chaque type pris en charge par PHP, à l'exception du type resource, peut être utilisé dans une déclaration de type par l'utilisateur. Cette page contient un journal des modifications de la disponibilité des différents types et de la documentation sur leur utilisation dans les déclarations de type.
Note:
Lorsqu'une classe implémente une méthode d'interface ou réimplémente une méthode qui a déjà été définie par une classe parente, elle doit être compatible avec la définition susmentionnée. Une méthode est compatible si elle suit les règles de variance.
Historique
Version | Description |
---|---|
8.2.0 | Ajout du support de type DNF (Forme Normale Disjonctive). |
8.2.0 | Ajout du support du type true. |
8.2.0 | Les type null et false peuvent désormais être utilisés de manière autonome. |
8.1.0 | La prise en charge des types d’intersection a été ajoutée. |
8.1.0 | Le renvoi par référence à partir d’une fonction void est désormais déconseillé. |
8.1.0 | La prise en charge du type de retour uniquement never a été ajoutée. |
8.0.0 | Ajout du support de mixed |
8.0.0 | La prise en charge du type de retour uniquement static a été ajoutée. |
8.0.0 | La prise en charge des types union a été ajoutée. |
7.2.0 | Ajout du support pour object. |
7.1.0 | Ajout du support pour iterable. |
7.1.0 | Ajout du support pour void. |
7.1.0 | La prise en charge des types nullable a été ajoutée. |
Notes d'utilisation des types de base
Les types de base ont un comportement direct avec quelques mises en garde mineures qui sont décrites dans cette section.
Types scalaires
Les alias pour les types scalaires (bool, int,
float, string) ne sont pas supportés.
À la place, ils sont traités comme des noms de classe ou d'interface.
Par exemple, utiliser boolean
comme une déclaration de
type nécessite que la valeur soit une instanceof
de la classe ou
interface boolean
, plutôt que de type
bool :
<?php
function test(boolean $param) {}
test(true);
?>
Résultat de l'exemple ci-dessus en 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
void
Note:
Le retour par référence à partir d’une fonction void est obsolète à partir de PHP 8.1.0, car une telle fonction est contradictoire. Auparavant, elle émettait déjà les
E_NOTICE
suivants lorsqu’elle était appelée :Seules les références de variables doivent être renvoyées par référence
.<?php
function &test(): void {}
?>
Types Callable
Ce type ne peut pas être utilisé comme déclaration de type de propriété de classe.
Note: Il n’est pas possible de spécifier la signature de la fonction.
Déclarations de type sur les paramètres de référence
Si un paramètre passé par référence à une déclaration de type, le type de la variable n’est vérifié qu’à l’entrée de la fonction, au début de l’appel, mais pas lorsque la fonction est de nouveau appelée. Cela signifie qu’une fonction peut modifier le type de la variable passée par référence.
Exemple #1 Paramètre typé passé par référence
<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>
Résultat de l'exemple ci-dessus est similaire à :
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
Notes d’utilisation des types composites
Les déclarations de type composite sont soumises à quelques restrictions et effectueront un contrôle de redondance au moment de la compilation pour éviter les bogues simples.
Antérieur à PHP 8.2.0 et l’introduction des types DNF, il n’était pas possible de combiner les intersections de type avec les unions de type.
Types d’unions
Il n’est pas possible de combiner les deux types littéraux
false
et true
ensemble dans une
union de type.
Utilisez plutôt bool.
Antérieur à PHP 8.2.0, comme false et null ne pouvaient pas être utilisés comme types autonomes, une union de type composé uniquement de ces types n’était pas autorisé. Cela comprend les types suivants : false, false|null et ?false.
Sucre syntaxique de type nullable
Une déclaration de type de base unique peut être marquée comme valeur NULL
en faisant précéder le type d’un point d’interrogation (?
).
Ainsi ?T
et T|null
sont identiques.
Note: Cette syntaxe est prise en charge à partir de PHP 7.1.0, et est antérieure à la prise en charge généralisée des unions de type.
Note:
Il est également possible d’obtenir des arguments nullable en faisant de
null
la valeur par défaut. Ceci n’est pas recommandé, car si la valeur par défaut est modifiée dans une classe enfant, une violation de compatibilité de type sera déclenchée car le type null devra être ajouté à la déclaration de type.Exemple #2 Ancienne façon de rendre les arguments nullables
<?php
class C {}
function f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>L'exemple ci-dessus va afficher :
object(C)#1 (0) { } NULL
Types dupliqués et redondants
Pour détecter des bogues simples dans les déclarations de type composite, les types redondants qui peuvent être détectés sans effectuer de chargement de classe entraîneront une erreur de compilation. Cela comprend :
-
Chaque type résolu par nom ne peut se produire qu’une seule fois.
Les types tels que
int|string|INT
ouCountable&Traversable&COUNTABLE
génèrent une erreur. - L’utilisation de mixed entraîne une erreur.
-
Pour les types d’unions :
- Si bool est utilisé, false ou true ne peut pas être utilisé en plus.
- Si object est utilisé, les types de classe ne peuvent pas être utilisés en plus.
- Si iterable est utilisé, array et Traversable ne peuvent pas être utilisés en plus.
-
Pour les types d’intersections :
- L’utilisation d’un type qui n’est pas un type de classe génère une erreur.
- L’utilisation de self, parent ou static entraîne une erreur.
-
Pour les type DNF :
- Si un type plus générique est utilisé, le plus restrictif est redondant.
- Utilisation de deux types d’intersection identiques.
Note: Cela ne garantit pas que le type est « minimal », car cela nécessiterait de charger tous les types de classe utilisés.
Par exemple, si A
et B
sont des
alias de classe, alors A|B
reste une union de type
légale, même s'il est possible de réduire à A
ou
B
.
De même, si la classe B extends A {}
, alors
A|B
est également une union de type légale, même s'il
pourrait être réduit au type A
uniquement.
<?php
function foo(): int|INT {} // Disallowed
function foo(): bool|false {} // Disallowed
function foo(): int&Traversable {} // Disallowed
function foo(): self&Traversable {} // Disallowed
use A as B;
function foo(): A|B {} // Disallowed ("use" is part of name resolution)
function foo(): A&B {} // Disallowed ("use" is part of name resolution)
class_alias('X', 'Y');
function foo(): X|Y {} // Allowed (redundancy is only known at runtime)
function foo(): X&Y {} // Allowed (redundancy is only known at runtime)
?>
Exemples
Exemple #3 Déclaration de type de classe de base
<?php
class C {}
class D extends C {}
// This doesn't extend C.
class E {}
function f(C $c) {
echo get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>
Résultat de l'exemple ci-dessus en 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
Exemple #4 Déclaration de type d’interface de base
<?php
interface I { public function f(); }
class C implements I { public function f() {} }
// This doesn't implement I.
class E {}
function f(I $i) {
echo get_class($i)."\n";
}
f(new C);
f(new E);
?>
Résultat de l'exemple ci-dessus en 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
Exemple #5 Déclaration de type de retour de base
<?php
function sum($a, $b): float {
return $a + $b;
}
// Note that a float will be returned.
var_dump(sum(1, 2));
?>
L'exemple ci-dessus va afficher :
float(3)
Exemple #6 Renvoi d’un objet
<?php
class C {}
function getC(): C {
return new C;
}
var_dump(getC());
?>
L'exemple ci-dessus va afficher :
object(C)#1 (0) { }
Exemple #7 Déclaration de type d’argument nullable
<?php
class C {}
function f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>
L'exemple ci-dessus va afficher :
object(C)#1 (0) { } NULL
Exemple #8 Déclaration de type de retour nullable
<?php
function get_item(): ?string {
if (isset($_GET['item'])) {
return $_GET['item'];
} else {
return null;
}
}
?>
Typage Strict
Par défaut, PHP va convertir les valeurs d'un mauvais type vers le type scalaire attendu tant que possible. Par exemple, une fonction, qui attend comme paramètre une string, à laquelle est passée un int recevra une variable de type string.
Il est possible d'activer le mode de typage strict fichier par fichier. Dans le mode strict, seule une variable correspondant exactement au type attendu dans la déclaration sera acceptée sinon une TypeError sera levée. La seule exception à cette règle est qu'une valeur de type int peut passer une déclaration de type float.
Les appels aux fonctions depuis des fonctions internes ne seront pas
affectés par la déclaration strict_types
.
Pour activer le mode strict, l'expression declare
est utilisée avec la
déclaration strict_types
:
Note:
Le typage strict s'applique aux appels de fonction effectués depuis l'intérieur d'un fichier dont le typage strict est actif, et non aux fonctions déclarées dans ce fichier. Si un fichier dont le typage strict n'est pas activé effectue un appel à une fonction qui a été définie dans un fichier dont le type strict est actif, la préférence de l'appelant (mode coercitif) sera respecté et la valeur sera forcée.
Note:
Le typage strict n'est défini que pour les déclarations de type scalaire.
Exemple #9 Typage strict pour les valeurs d'arguments
<?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));
?>
Résultat de l'exemple ci-dessus en 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
Exemple #10 Typage coercitif pour les valeurs d'arguments
<?php
function sum(int $a, int $b) {
return $a + $b;
}
var_dump(sum(1, 2));
// These will be coerced to integers: note the output below!
var_dump(sum(1.5, 2.5));
?>
L'exemple ci-dessus va afficher :
int(3) int(3)
Exemple #11 Typage strict pour les valeurs de retour
<?php
declare(strict_types=1);
function sum($a, $b): int {
return $a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>
L'exemple ci-dessus va afficher :
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
Version en cache
05/11/2024 22:25:06 Cette version de la page est en cache (à la date du 05/11/2024 22:25:06) afin d'accélérer le traitement. Vous pouvez activer le mode utilisateur dans le menu en haut pour afficher la dernère version de la page.Document créé le 30/01/2003, dernière modification le 26/10/2018
Source du document imprimé : https://www.gaudry.be/php-rf-language.types.declarations.html
L'infobrol est un site personnel dont le contenu n'engage que moi. Le texte est mis à disposition sous licence CreativeCommons(BY-NC-SA). Plus d'info sur les conditions d'utilisation et sur l'auteur.
Références
Ces références et liens indiquent des documents consultés lors de la rédaction de cette page, ou qui peuvent apporter un complément d'information, mais les auteurs de ces sources ne peuvent être tenus responsables du contenu de cette page.
L'auteur de ce site est seul responsable de la manière dont sont présentés ici les différents concepts, et des libertés qui sont prises avec les ouvrages de référence. N'oubliez pas que vous devez croiser les informations de sources multiples afin de diminuer les risques d'erreurs.