整数变量除以另一个整数变量的不均匀除法将通过自动转换得到一个浮点数——您不必将变量转换为浮点数以避免整数截断(例如,在 C 中您需要这样做)。
$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
PHP 不需要在变量声明中显式定义类型。在这种情况下,变量的类型由它存储的值决定。也就是说,如果一个字符串赋值给变量$var,则$var的类型为字符串。如果之后一个整数值赋值给$var,则它的类型将变为整数。
在某些情况下,PHP可能会尝试自动将值的类型转换为另一种类型。存在的不同上下文是:
注意:当需要将值解释为不同类型时,值本身不会改变类型。
要强制变量被评估为特定类型,请参阅关于类型转换的部分。要更改变量的类型,请参阅settype()函数。
这是使用算术运算符时的上下文。
在此上下文中,如果任何一个操作数是浮点数(或不能解释为整数),则两个操作数都将被解释为浮点数,结果也将为浮点数。否则,操作数将被解释为整数,结果也将为整数。从PHP 8.0.0开始,如果其中一个操作数无法解释,则会抛出TypeError。
这是使用echo,print,字符串插值或字符串连接运算符时的上下文。
在此上下文中,该值将被解释为字符串。如果该值无法解释,则会抛出TypeError。在PHP 7.4.0之前,会引发E_RECOVERABLE_ERROR
。
这是使用位运算符时的上下文。
在此上下文中,如果所有操作数都是字符串类型,则结果也将是字符串。否则,操作数将被解释为整数,结果也将是整数。从PHP 8.0.0开始,如果其中一个操作数无法解释,则会抛出TypeError。
这是将值传递给类型化参数、属性或从声明返回类型的函数返回值时的上下文。
在此上下文中,该值必须是该类型的值。存在两个例外:第一种情况是:如果该值的类型是整数,而声明的类型是浮点数,则整数将转换为浮点数。第二种情况是:如果声明的类型是标量类型,该值可转换为标量类型,并且强制类型转换模式处于活动状态(默认值),则该值可能会转换为可接受的标量值。请参见下文对此行为的描述。
当未启用strict_types
时,标量类型声明会受到有限的隐式类型强制转换。如果值的精确类型不是联合类型的一部分,则目标类型将按照以下优先顺序选择:
注意:
示例 #1 类型被强制转换为联合类型一部分的示例
<?php
// int|string
42 --> 42 // 精确类型
"42" --> "42" // 精确类型
new ObjectWithToString --> "Result of __toString()"
// 对象与int类型不兼容,回退到string类型
42.0 --> 42 // float类型与int类型兼容
42.1 --> 42 // float类型与int类型兼容
1e100 --> "1.0E+100" // float类型太大,无法转换为int类型,回退到string类型
INF --> "INF" // float类型太大,无法转换为int类型,回退到string类型
true --> 1 // bool类型与int类型兼容
[] --> TypeError // 数组与int或string类型不兼容
// int|float|bool
"45" --> 45 // 整数型字符串
"45.0" --> 45.0 // 浮点型字符串
"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)
转换的别名。这些转换不使用规范类型名称,不推荐使用。
从 PHP 8.0.0 开始,(real)
转换别名已弃用。
从 PHP 7.2.0 开始,(unset)
转换已弃用。请注意,(unset)
转换与为变量赋值 NULL 或调用相同。(unset)
转换在 PHP 8.0.0 中已移除。
(binary)
转换和 b
前缀是为了向前兼容而存在的。目前 (binary)
和 (string)
是相同的,但这可能会改变,不应该依赖于此。
注意:
在转换的括号内,空格会被忽略。因此,以下两个转换是等效的:
<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>
注意: 除了将变量转换为 string 之外,还可以用双引号括起变量。
<?php
$foo = 10; // $foo 是一个整数
$str = "$foo"; // $str 是一个字符串
$fst = (string) $foo; // $fst 也是一个字符串
// 这将输出 "they are the same"
if ($fst === $str) {
echo "they are the same";
}
?>
在某些类型之间进行转换时,结果可能并不显而易见。更多信息,请参见以下章节:
注意: 因为 PHP 支持使用与 array 索引相同的语法对 string 进行偏移量索引,所以以下示例对所有 PHP 版本都成立:
更多信息,请参见标题为 按字符访问字符串 的章节。<?php
$a = 'car'; // $a 是一个字符串
$a[0] = 'b'; // $a 仍然是一个字符串
echo $a; // bar
?>
整数变量除以另一个整数变量的不均匀除法将通过自动转换得到一个浮点数——您不必将变量转换为浮点数以避免整数截断(例如,在 C 中您需要这样做)。
$dividend = 2;
$divisor = 3;
$quotient = $dividend/$divisor;
print $quotient; // 0.66666666666667
强制转换运算符具有非常高的优先级,例如 (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) 中,强制转换最后对变量表达式的结果执行]。
将对象转换为数组很麻烦。示例:
<?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',因此在操作这些键时需要注意。
如果要自动将字符串转换为浮点数或整数(例如,将“0.234”转换为浮点数,将“123”转换为整数),只需向字符串添加 0 —— PHP 会完成其余工作。
例如:
$val = 0 + "1.234";
($val 的类型现在是浮点数)
$val = 0 + "123";
($val 的类型现在是整数)
此处介绍的对象转换方法没有考虑尝试将对象转换到的类的类层次结构。
/**
* 将对象转换为特定类。
* @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;
}
}
有一些更短更快(至少在我的机器上)的方法可以执行类型转换。
<?php
$string='12345.678';
$float=+$string;
$integer=0|$string;
$boolean=!!$string;
?>