在PHP中,变量声明时不需要显式定义类型。在这种情况下,变量的类型由存储的值决定。也就是说,如果将字符串赋值给var,那么var的类型就是字符串。之后将整数值赋值给$var,它将是整数类型。这种特性使得PHP在处理不同类型的数据时更加灵活。
PHP 可能会尝试在某些上下文中自动将值转换为另一种类型。不同的上下文有:
- Numeric
- String
- Logical
- Integral and string
- Comparative
- Function
注意: 当值需要解释为不同类型时,值本身不会改变类型。
一、Numeric contexts
如果任一运算对象是 float(或者不能解释为 int),则两个运算对象都将解释为 float,结果也将是 float。否则,运算对象将解释为 int,结果也将是 int。自 PHP 8.0.0 起,如果无法解释其中一个运算对象,则会抛出 TypeError。
二、String contexts
这种情况下,值将会解释为 string。如果值无法解释,那么会抛出 TypeError。在 PHP 7.4.0 之前,会引发 E_RECOVERABLE_ERROR。
三、Logical contexts
在这种情况下,值将会解释为 bool。
四、Integral and string contexts
在这种情况下,如果所有的运算对象都是 string,则结果也将是 string。否则运算对象将解释为 int,结果也将是 int。如果其中一个运算对象无法解释,则会抛出 TypeError。
五、Function contexts
在此上下文中,值必须是类型值。但存在两个例外,第一个是如果值为 int,但声明的类型是 float,然后整数会转换为浮点数。第二个是如果声明的类型是 scalar 类型,值可转换为标量类型,并且强制类型模式处于活动状态(默认),值会转换为可接受的标量值。下文会列出有关此行为的描述。
注意:内部函数自动将 null 转换为标量类型,此行为自 PHP 8.1.0 起弃用。
1、使用简单类型声明的强制类型
- bool 类型声明:值将解释为 bool。
- int 类型声明:如果明确定义转换,则值将解释为 int。例如,字符串是数字。
- float 类型声明:如果明确定义转换,则值将解释为 float。例如,字符串是数字。
- string 类型声明:值将解释为 string。
2、使用联合类型的强制类型
当strict_types未启用时,标量类型声明将受到有限的隐式类型强制转换。如果值的精确类型不是联合的一部分,然后会按照以下优先顺序选择目标类型:
- int
- float
- string
- bool
如果类型存在于联合中并且该值可以通过PHP现有的类型检查语义强制转换为该类型,则选择该类型。否则,建议尝试下一个类型。
注意:一个例外,如果值是字符串,并且 int 和 float 都是联合类型的一部分,首选类型则通过现有的数字字符串语义决定。例如 “42” 选择 int,”42.0″ 选择 float。
不属于上述偏好列表的类型没有资格进行隐式强制转换。特别是不会发生隐式强制转换为null、false和true类型的情况。
示例:将类型强制转换为联合类型
<?php // int|string 42 --> 42 // exact type "42" --> "42" // exact type new ObjectWithToString --> "Result of __toString()" // object never compatible with int, fall back to string 42.0 --> 42 // float compatible with int 42.1 --> 42 // float compatible with int 1e100 --> "1.0E+100" // float too large for int type, fall back to string INF --> "INF" // float too large for int type, fall back to string true --> 1 // bool compatible with int [] --> TypeError // array not compatible with int or string // int|float|bool "45" --> 45 // int numeric string "45.0" --> 45.0 // float numeric string "45X" --> true // not numeric string, fall back to bool "" --> false // not numeric string, fall back to bool "X" --> true // not numeric string, fall back to bool [] --> TypeError // array not compatible with int, float or bool ?>
六、类型转换
类型转换通过在值前面的括号中写入类型来将值转换指定的类型。
<?php $foo = 10; // $foo 是 int $bar = (bool) $foo; // $bar 是 bool ?>
允许的转换是:
- (int) :转换为 int
- (bool):转换为 bool
- (float):转换为 float
- (string):转换为 string
- (array):转换为 array
- (object):转换为 object
- (unset):转换为 NULL
注意:
- (integer) 是 (int) 转换的别名。(boolean) 是 (bool) 转换的别名。(binary) 是 (string) 转换的别名。(double) 和 (real) 是 (float) 转换的别名。这些转换不使用标准的类型名称,不推荐使用。
- 自 PHP 8.0.0 起弃用 (real) 转换别名。
- 自 PHP 7.2.0 起弃用 (unset) 转换。注意 (unset) 转换等同于将值 NULL 通过赋值或者调用给变量。自 PHP 8.0.0 起移除 unset 转换。
- 向前兼容 (binary) 转换和 b 前缀转换。注意 (binary) 转换和 (string) 相同,但是这可能会改变且不应依赖。
在转换的括号内忽略空格。因此,以下两个转换是等价的:
<?php $foo = (int) $bar; $foo = ( int ) $bar; ?>
将文字 string 和变量转换为二进制 string:
<?php $binary = (binary) $string; $binary = b"binary string"; ?>
除了将变量转换为 string 之外,还可以将变量放在双引号内。
<?php $foo = 10; // $foo 是 int $str = "$foo"; // $str 是 string $fst = (string) $foo; // $fst 也是 string // 打印出 "they are the same" if ($fst === $str) { echo "they are the same"; } ?>
有时在类型之间转换时确切地会发生什么可能不是很明显。更多信息见如下部分:
转换为 bool:《PHP Boolean 布尔类型》
转换为 int:《PHP Integer 整型》
转换为 float:《PHP Float 浮点型》
转换为 string:《PHP String 字符串》
转换为 array:《PHP Array数组》
转换为 object:《PHP Object 对象》
因为 PHP 的 string 支持使用与 array 索引相同的语法,通过偏移量进行索引,所以以下示例适用于所有 PHP 版本:
<?php $a = 'car'; // $a 是 string $a[0] = 'b'; // $a 依然是 string echo $a; // bar ?>