类型转换

PHP 不需要在变量声明中显式定义类型。在这种情况下,变量的类型由它存储的值决定。也就是说,如果将一个 字符串 赋值给变量 $var,那么 $var 的类型为 字符串。如果之后将一个 整数 值赋值给 $var,它将是 整数 类型。

PHP 可能会尝试在某些情况下自动将一个值的类型转换为另一个类型。存在的不同上下文是

  • 数值
  • 字符串
  • 逻辑
  • 整数和字符串
  • 比较
  • 函数

注意当需要将一个值解释为不同的类型时,该值本身不会更改类型。

要强制变量被评估为特定类型,请参阅关于 类型转换 的部分。要更改变量的类型,请参阅 settype() 函数。

数值上下文

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

在此上下文中,如果任一操作数为 浮点数(或不能解释为 整数),则两个操作数都将被解释为 浮点数,结果将为 浮点数。否则,操作数将被解释为 整数,结果也将为 整数。从 PHP 8.0.0 开始,如果其中一个操作数无法解释,则会抛出 TypeError

字符串上下文

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

在此上下文中,该值将被解释为 字符串。如果该值无法解释,则会抛出 TypeError。在 PHP 7.4.0 之前,会引发一个 E_RECOVERABLE_ERROR

逻辑上下文

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

在此上下文中,该值将被解释为 布尔值

整数和字符串上下文

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

在此上下文中,如果所有操作数的类型均为 字符串,则结果也将为 字符串。否则,操作数将被解释为 整数,结果也将为 整数。从 PHP 8.0.0 开始,如果其中一个操作数无法解释,则会抛出 TypeError

比较上下文

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

在此上下文中发生的类型转换在 表格 中的“与各种类型的比较”部分中解释。

函数上下文

这是将值传递给类型化参数、属性或从声明返回类型的函数返回时所处的上下文。

在此上下文中,该值必须是该类型的值。存在两个例外,第一个是:如果该值的类型为 整数 且声明的类型为 浮点数,则整数将转换为浮点数。第二个是:如果声明的类型是标量类型,该值可转换为标量类型,且强制类型模式处于活动状态(默认值),则该值可能会转换为可接受的标量值。请参阅下文以了解此行为的描述。

警告

内部函数 会自动将 null 强制转换为标量类型,此行为从 PHP 8.1.0 开始已弃用

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

使用联合类型的强制类型

strict_types 未启用时,标量类型声明会受到有限的隐式类型强制的约束。如果该值的精确类型不是联合类型的一部分,则目标类型将按照以下优先顺序选择

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

注意

作为例外,如果该值是一个字符串,并且 int 和 float 都是联合类型的一部分,则首选类型由现有的 数值字符串 语义确定。例如,对于 "42" 选择 整数 类型,而对于 "42.0" 选择 浮点数 类型。

注意:

不属于上述优先级列表中的类型没有资格成为隐式强制的目标。特别是不会发生到 nullfalsetrue 类型的隐式强制。

示例 #1 类型被强制转换为联合类型的一部分的示例

<?php
// int|string
42 --> 42 // 精确类型
"42" --> "42" // 精确类型
new ObjectWithToString --> "Result of __toString()"
// 对象永远不兼容 int,回退到字符串
42.0 --> 42 // float 兼容 int
42.1 --> 42 // float 兼容 int
1e100 --> "1.0E+100" // float 对于 int 类型过大,回退到字符串
INF --> "INF" // float 对于 int 类型过大,回退到字符串
true --> 1 // bool 兼容 int
[] --> TypeError // 数组不兼容 int 或字符串

// int|float|bool
"45" --> 45 // int 数值字符串
"45.0" --> 45.0 // float 数值字符串

"45X" --> true // 不是数值字符串,回退到 bool
"" --> false // 不是数值字符串,回退到 bool
"X" --> true // 不是数值字符串,回退到 bool
[] --> TypeError // 数组不兼容 int、float 或 bool
?>

类型转换

类型转换通过在要转换的值之前用括号括起来类型来转换该值。

<?php
$foo
= 10; // $foo 是一个整数
$bar = (bool) $foo; // $bar 是一个布尔值
?>

允许的强制转换

  • (int) - 强制转换为 int
  • (bool) - 强制转换为 bool
  • (float) - 强制转换为 float
  • (string) - 强制转换为 string
  • (array) - 强制转换为 array
  • (object) - 强制转换为 object
  • (unset) - 强制转换为 NULL

注意:

(integer)(int) 强制转换的别名。 (boolean)(bool) 强制转换的别名。 (binary)(string) 强制转换的别名。 (double)(real)(float) 强制转换的别名。这些强制转换不使用规范类型名称,不推荐使用。

警告

(real) 强制转换别名已从 PHP 8.0.0 开始弃用。

警告

(unset) 强制转换已从 PHP 7.2.0 开始弃用。请注意,(unset) 强制转换与将值 NULL 赋值给变量或调用相同。 (unset) 强制转换已从 PHP 8.0.0 开始移除。

注意

(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 是一个整数
$str = "$foo"; // $str 是一个字符串
$fst = (string) $foo; // $fst 也是一个字符串

// 这将打印出“它们相同”
if ($fst === $str) {
echo
"they are the same";
}
?>

在某些类型之间强制转换时,确切的结果可能并不明显。有关更多信息,请参阅以下部分

注意: 由于 PHP 支持使用与 array 索引相同的语法通过偏移量索引 string,因此以下示例对所有 PHP 版本都成立:

<?php
$a
= 'car'; // $a 是一个字符串
$a[0] = 'b'; // $a 仍然是一个字符串
echo $a; // bar
?>
有关更多信息,请参阅名为 按字符访问字符串 的部分。

添加说明

用户贡献的说明 7 条说明

Raja
19 年前
整数变量除以另一个整数变量的不均匀除法将通过自动转换生成浮点数 - 您不必将变量强制转换为浮点数以避免整数截断(例如在 C 中)。

$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
fardelian
11 年前
将对象强制转换为数组很麻烦。示例

<?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
)
*/

?>

是的,这看起来像一个包含两个相同名称键的数组,并且看起来受保护的字段已添加星号作为前缀。但事实并非如此

<?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
*/

?>

字符代码显示受保护的键以 '\0*\0' 作为前缀,私有键以 '\0' 作为前缀。__CLASS__.'\0',因此在使用此功能时要小心。
Anonymous
3 年前
强制转换运算符具有非常高的优先级,例如 (int)$a/$b 将被评估为 ((int)$a)/$b,而不是 (int)($a/$b) [如果 $a 和 $b 都是整数,这就像 intdiv($a,$b) 一样]。
唯一的例外(截至 PHP 8.0)是指数运算符 ** [即 (int)$a**$b 被评估为 (int)($a**$b) 而不是 ((int)$a)**$b] 和特殊访问/调用运算符 ->,::,[] 和 () [即在 (int)$a->$b,(int)$a::$b,(int)$a[$b] 和 (int)$a($b) 中,强制转换最后在变量表达式的结果上执行]。
miracle at 1oo-percent dot de
18 年前
如果您希望自动将字符串转换为浮点数或整数(例如,将“0.234”转换为浮点数,将“123”转换为整数),只需在字符串中添加 0 - PHP 会完成剩下的工作。

例如

$val = 0 + "1.234";
(现在 $val 的类型为浮点数)

$val = 0 + "123";
(现在 $val 的类型为整数)
rmirabelle
13 年前
这里介绍的对象强制转换方法没有考虑您尝试将对象强制转换为的类的类层次结构。

/**
* 将对象转换为特定类。
* @param object $object
* @param string $class_name 要将对象强制转换为的类
* @return object
*/
public static function cast($object, $class_name) {
if($object === false) return false;
if(class_exists($class_name)) {
$ser_object = serialize($object);
$obj_name_len = strlen(get_class($object));
$start = $obj_name_len + strlen($obj_name_len) + 6;
$new_object = 'O:' . strlen($class_name) . ':"' . $class_name . '":';
$new_object .= substr($ser_object, $start);
$new_object = unserialize($new_object);
/**
* 新对象是正确类型,但
* 整个图尚未完全初始化。
* 要获得完整对象图(包括父
* 类数据,我们需要创建一个新的实例
* 指定的类,然后将新的
* 属性赋予它。
*/
$graph = new $class_name;
foreach($new_object as $prop => $val) {
$graph->$prop = $val;
}
return $graph;
} else {
throw new CoreException(false, "在 DB::cast 中找不到用于转换的类 $class_name");
return false;
}
}
匿名
21 年前
打印或回显 FALSE 布尔值或 NULL 值将得到一个空字符串
(string)TRUE //返回 "1"
(string)FALSE //返回 ""
echo TRUE; //打印 "1"
echo FALSE; //不打印任何内容!
ieee at REMOVE dot bk dot ru
12 年前
有一些更短更快(至少在我的机器上)的方法来执行类型转换。
<?php
$string
='12345.678';
$float=+$string;
$integer=0|$string;
$boolean=!!$string;
?>
To Top