PHP Conference Kansai 2025

类型转换

PHP 在变量声明时不需要定义类型。在这种情况下,变量的类型由存储的值决定。也就是说,如果 string 赋值给 $var,然后 $var 的类型就是 string。之后将 int 值赋值给 $var,它将是 int 类型。

PHP 可能会尝试在某些上下文中自动将值转换为另一种类型。不同的上下文有:

  • Numeric
  • String
  • Logical
  • Integral and string
  • Comparative
  • Function

注意: 当值需要解释为不同类型时,值本身会改变类型。

强制将变量当做某种变量来求值,参见类型转换一节。要更改变量的类型,请参阅 settype() 函数。

数字上下文

使用算术运算符时的上下文。

在这种情况下,如果任一运算对象是 float(或者不能解释为 int),则两个运算对象都将解释为 float,结果也将是 float。否则,运算对象将解释为 int,结果也将是 int。自 PHP 8.0.0 起,如果无法解释其中一个运算对象,则会抛出 TypeError

字符串上下文

使用 echoprint字符串插值或者字符串连接运算符时的上下文。

这种情况下,值将会解释为 string。如果值无法解释,那么会抛出 TypeError。在 PHP 7.4.0 之前,会引发 E_RECOVERABLE_ERROR

逻辑上下文

使用条件语句、三元运算符逻辑运算符时的上下文。

在这种情况下,值将会解释为 bool

整数和字符串上下文

使用位运算符时的上下文。

在这种情况下,如果所有的运算对象都是 string,则结果也将是 string。否则运算对象将解释为 int,结果也将是 int。如果其中一个运算对象无法解释,则会抛出 TypeError

比较上下文

使用比较运算符时的上下文。

在此上下文中发生的类型转换在比较多种类型中进行了说明。

函数上下文

将值传递给已声明类型的参数、属性,或从声明了返回类型的函数返回值时的上下文。

在此上下文中,值必须是类型值。但存在两个例外,第一个是如果值为 int,但声明的类型是 float,然后整数会转换为浮点数。第二个是如果声明的类型是 scalar 类型,值可转换为标量类型,并且强制类型模式处于活动状态(默认),值会转换为可接受的标量值。参见下文查看有关此行为的描述。

警告

内部函数自动将 null 转换为标量类型,此行为自 PHP 8.1.0 起弃用

使用简单类型声明的强制类型

  • bool 类型声明:值将解释为 bool
  • int 类型声明:如果明确定义转换,则值将解释为 int。例如,字符串是数字
  • float 类型声明:如果明确定义转换,则值将解释为 float。例如,字符串是数字
  • string 类型声明:值将解释为 string

使用联合类型的强制类型

当未启用 strict_types 时,声明的标量类型会受到有限的隐式类型转换的影响。如果值的精确类型不是联合的一部分,然后会按照以下优先顺序选择目标类型:

  1. int
  2. float
  3. string
  4. bool
如果类型存在于 union 类型中,并且值可以根据 PHP 现有的类型检查语义转换为此类型,则选择该类型。否则,尝试下一个类型

警告

有个例外,如果值是字符串,并且 int 和 float 都是联合类型的一部分,首选类型则通过现有的数字字符串语义决定。例如 "42" 选择 int"42.0" 选择 float

注意:

不属于上述优先级列表的类型不会进行隐式转换。特别是,不会出现对 nullfalsetrue 类型的隐式转换。

示例 #1 类型转换为 union 类型中的一个的示例

<?php
// int|string
42    --> 42          // 具体类型
"42"  --> "42"        // 具体类型
new ObjectWithToString --> "Result of __toString()"
                      // 对象绝不会兼容 int,回退到 string
42.0  --> 42          // int 兼容 float
42.1  --> 42          // int 兼容 float
1e100 --> "1.0E+100"  // float 对于 int 类型来说太大了,回退为 string
INF   --> "INF"       // float 对于 int 类型来说太大了,回退为 string
true  --> 1           // int 兼容 bool
[]    --> TypeError   // int 或 string 不兼容 array

// int|float|bool
"45"    --> 45        // int 数字 string
"45.0"  --> 45.0      // float 数字 string

"45X"   --> true      // 不是 numeric string,回退为 bool
""      --> false     // 不是 numeric string,回退为 bool
"X"     --> true      // 不是 numeric string,回退为 bool
[]      --> TypeError // int、float 或 bool 不兼容 array
?>

类型转换

类型转换通过在值前面的括号中写入类型来将值转换指定的类型。

示例 #2 类型转换

<?php
$foo
= 10; // $foo 是 int
$bar = (bool) $foo; // $bar 是 bool

var_dump($bar);
?>

允许的转换是:

  • (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 之外,还可以将变量放在双引号内。

示例 #3 不同的转换机制

<?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", PHP_EOL;
}
?>

有时在类型之间转换时确切地会发生什么可能不是很明显。更多信息见如下不分:

注意: 因为 PHP 的 string 支持使用与 array 索引相同的语法,通过偏移量进行索引,所以以下示例适用于所有 PHP 版本:

示例 #4 使用字符串的数组偏移

<?php
$a
= 'car'; // $a 是 string
$a[0] = 'b'; // $a 依然是 string
echo $a; // bar
?>
请查看章节标题为存取和修改字符串中的字符获取更多信息。

添加备注

用户贡献的备注 6 notes

up
75
Raja
20 years ago
Uneven division of an integer variable by another integer variable will result in a float by automatic conversion -- you do not have to cast the variables to floats in order to avoid integer truncation (as you would in C, for example):

$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
up
18
Anonymous
4 years ago
Cast operators have a very high precedence, for example (int)$a/$b is evaluated as ((int)$a)/$b, not as (int)($a/$b) [which would be like intdiv($a,$b) if both $a and $b are integers].
The only exceptions (as of PHP 8.0) are the exponentiation operator ** [i.e. (int)$a**$b is evaluated as (int)($a**$b) rather than ((int)$a)**$b] and the special access/invocation operators ->, ::, [] and () [i.e. in each of (int)$a->$b, (int)$a::$b, (int)$a[$b] and (int)$a($b), the cast is performed last on the result of the variable expression].
up
27
fardelian
12 years ago
Casting objects to arrays is a pain. Example:

<?php

class MyClass {

private
$priv = 'priv_value';
protected
$prot = 'prot_value';
public
$pub = 'pub_value';
public
$MyClasspriv = 'second_pub_value';

}

$test = new MyClass();
echo
'<pre>';
print_r((array) $test);

/*
Array
(
[MyClasspriv] => priv_value
[*prot] => prot_value
[pub] => pub_value
[MyClasspriv] => second_pub_value
)
*/

?>

Yes, that looks like an array with two keys with the same name and it looks like the protected field was prepended with an asterisk. But that's not true:

<?php

foreach ((array) $test as $key => $value) {
$len = strlen($key);
echo
"{$key} ({$len}) => {$value}<br />";
for (
$i = 0; $i < $len; ++$i) {
echo
ord($key[$i]) . ' ';
}
echo
'<hr />';
}

/*
MyClasspriv (13) => priv_value
0 77 121 67 108 97 115 115 0 112 114 105 118
*prot (7) => prot_value
0 42 0 112 114 111 116
pub (3) => pub_value
112 117 98
MyClasspriv (11) => second_pub_value
77 121 67 108 97 115 115 112 114 105 118
*/

?>

The char codes show that the protected keys are prepended with '\0*\0' and private keys are prepended with '\0'.__CLASS__.'\0' so be careful when playing around with this.
up
14
miracle at 1oo-percent dot de
19 years ago
If you want to convert a string automatically to float or integer (e.g. "0.234" to float and "123" to int), simply add 0 to the string - PHP will do the rest.

e.g.

$val = 0 + "1.234";
(type of $val is float now)

$val = 0 + "123";
(type of $val is integer now)
up
19
Anonymous
22 years ago
Printing or echoing a FALSE boolean value or a NULL value results in an empty string:
(string)TRUE //returns "1"
(string)FALSE //returns ""
echo TRUE; //prints "1"
echo FALSE; //prints nothing!
up
2
Anonymous
6 months ago
Type casting in expressions is executed first.
The casting is assigned to the value, not to the expression result.
Examples:

<?php

$string
= "777";

var_dump( $string === 777 ); // FALSE
var_dump( (int) $string === 777 ); // TRUE
var_dump( ( (int) $string ) === 777 ); // TRUE
var_dump( (int) ( $string === 777 ) ); // 0
?>
To Top
OSZAR »