PHP7.4.0以后,为了明确指定所需类型,可以在函数的参数、返回值及类属性中使用类型声明。如果调用时期望的类型不匹配,则抛出TypeError异常。
注意:
如果子类覆盖父方法,则子类方法必须与超类的类型声明匹配。如果在父类中未定义返回值类型,则子方法可以指定自己的返回值类型。
类/接口名称值必须是指定类和接口instanceof的实例
self值必须是用于类型声明的同一类的instanceof。仅在类中可用。
父代值必须是类型声明的父类的instanceof,并且只能在类中使用。
数组值必须是数组。
callable值必须是有效的callable。不能用于类属性的类型声明。
布尔值必须为布尔值。
浮点值必须是浮点数。
整型值必须是整数。
字符串值必须是字符串。
可度量值必须是可信数组或实例。PHP 7.1.0
对象值必须为object。PHP 7.2.0
混合值可以是任何类型。PHP 8.0.0
注意:
不支持上述标量类型的别名。而是被视为类或接口名称。例如,要将布尔用作类型声明,值必须是类或接口实例的布尔,而不是布尔类型。
<?php function test(boolean $param) {} test(true); ?>
以上例程在 PHP 8 中的输出:
Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "oolean" 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等于union类型的object。PHP8.0.0以后可以使用。
示例1在类中使用类型声明:
<?php class C {} class D extends C {} // 它没有 extend C。 class E {} function f(C $c) { echo get_class($c)." "; } f(new C); f(new D); f(new E); ?>
以上例程在 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
示例2在接口中使用类型声明:
<?php interface I { public function f(); } class C implements I { public function f() {} } // 它没有 implement I。 class E {} function f(I $i) { echo get_class($i)." "; } f(new C); f(new E); ?>
以上例程在 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
实例#3声明返回类型:
<?php function sum($a, $b): float { return $a + $b; } // 注意必须返回一个 float。 var_dump(sum(1, 2)); ?>
以上例程会输出:
float(3)
示例4返回对象:
<?php class C {} function getC(): C { return new C; } var_dump(getC()); ?>
以上例程会输出:
object(C)#1 (0) {
}
允许空Nullable类型
在PHP7.1.0中,在类型声明之前使用问号(?)中描述的场景,使用下列步骤创建明细表,以便在概念设计中分析体量的周长。
定义实例#5空允许参数类型:
<?php class C {} function f(?C $c) { var_dump($c); } f(new C); f(null); ?>
以上例程会输出:
object(C)#1 (0) {
}
NULL
示例 #6 定义可空(Nullable)的返回类型
<?php function get_item(): ?string { if (isset($_GET['item'])) { return $_GET['item']; } else { return null; } } ?>
注意:
若要允许空参数,请将参数的默认值设置为空。不建议这样做,因为它会影响类继承调用。
实例#7允许旧版本的空参数的实现示例:
<?php class C {} function f(C $c = null) { var_dump($c); } f(new C); f(null); ?>
以上例程会输出:
object(C)#1 (0) {
}
NULL
也可以将简单类型组合为复合类型。PHP支持复合型:
简单型的联合。PHP8.0.0以后可以使用。
接口、类名类型的公共部分。PHP8.1.0以后可以使用。
注意:
交叉点型和联合型不能合成。
联合类型接受多个不同的简单类型作为参数。用于声明共享体型的语法是T1。Union型在PHP8.0.0以后可以使用。
允许空的联合类型
null型可以在共用体型中使用。例如,T1|T2|null接受null作为参数。现有的?可以将T语法视为以下共享体型T的缩写:。
注意:
不能将空值用作独立类型。
由于历史原因,许多内部函数在失败时返回false,而不是null。此类函数的典型示例是strpos()。
注意:
不能单独将假作为类型使用(包括空可接受类型)。因此,假、假、?不能使用假。
注意:
不存在真正的文字类型。
只要满足class-type的值,就可以在交叉型声明中使用,可以使用多个值。交叉点类型由语法T1&T2&…指定。相交类型可从PHP8.1.0开始使用。
冗余重复
为了澄清复合声明中的简单错误,重复冗余类型可能会在编译时出错,而不加载类。包括:
分析的类型只能显示一次。例如,“整型”、“可组合”和“可组合”等类型将出错。
混合的结果会导致错误。
对于联合类型:
现在不能和bool一起使用false了。
使用对象时,类类型不可用。
erable时,array和Traversable都不能一起使用。
对于相交类型:
如果使用非class-type类型,则会发生错误。
如果使用self、parent和static,则全部都会出错。
注意:但不能保证最小化类型。要执行此操作,还将导入使用该类型的类。
例如,假设A和B都是类的别名,并且即使可以缩小到A或B,A|B仍然有效。同样,如果B扩展A{},则A|B是有效的共享体型,但可以缩小为A。
<?php function foo(): int|INT {} // 不允许 function foo(): bool|false {} // 不允许 function foo(): int&Traversable {} // 不允许 function foo(): self&Traversable {} // 不允许 use A as B; function foo(): A|B {} // 不允许 ("use" 是名称解析的一部分) function foo(): A&B {} // 不允许 ("use" 是名称解析的一部分) class_alias('X', 'Y'); function foo(): X|Y {} // 允许 (运行时才能知道重复性) function foo(): X&Y {} // 允许 (运行时才能知道重复性) ?>
默认情况下,如果可能,PHP将不适当的类型强制转换为所需的标量类型。例如,如果参数需要字符串,并且传递了整型,则会检索字符串类型的变量。
可以为每个文件打开Strict模式。严格模式仅接受精确匹配的类型。否则将抛出类型错误。唯一的例外是,也可以以声明为浮动的类型传递整型值。
注意:
如果通过内部函数调用函数,则strict_types声明不受影响。
要启用strict模式,请使用declare将strict_类型。
提示:
在文件中启用严格的类型指定后,内部调用的函数将应用严格的类型指定,而不是在声明的文件中启用函数。如果文件未被声明为启用严格的类型指定,并且调用函数所在的文件具有严格的类型声明,则根据调用方的设置(启用类型强制),值也将被强制。
提示:
严格的类型指定仅为标量类型声明启用。