提问人:Matrix 提问时间:2/28/2022 最后编辑:DharmanMatrix 更新时间:5/21/2023 访问量:5767
PHP 8 严格类型是强制执行本机函数的吗?
PHP 8 strict type is forced on native function?
问:
我的代码适用于 PHP 7:
round(microtime(),3);
但在 PHP 8 中:
致命错误:未捕获的 TypeError:round():参数 #1 ($num) 必须是 int|float 类型,字符串在 [...] 中给出[...]:4 堆栈跟踪:#0 [...]...: round('0.21066100 1646...', 3) #1 {main} 扔进去 [...][...]4号线
如果我强制施法:
round((float)microtime(),3);
它有效,但PHP的所有力量都是自动转换和非严格类型!如果必须编辑我所有数十亿行代码中的所有本机函数以强制强制转换到任何地方,我如何使用 PHP 8?
有没有办法在内部函数上保留自动类型转换?
我在代码中以 microtime() 为例,但是:
round("200 42");
作为同样的问题,所以解决方案不仅仅是,这不是这里的话题。microtime(true)
问题是,如果我在我的代码中使用本机函数,则存在潜在的错误并且我无法知道它(错误仅在脚本运行时发生),因此,如果我让 PHP 8 运行,可能会,我的网站的某些页面无法正常工作,我不可能知道它!这是一个大问题!
https://www.php.net/manual/en/migration80.other-changes.php
数学函数 abs()、ceil()、floor() 和 round() 现在正确 注意strict_types指令。以前,他们胁迫了第一个 即使在严格类型模式下也是如此。
因此,此函数必须专注于更新代码,而不是所有本机函数!
答:
除非声明,否则无需强制转换以匹配所有位置的本机函数签名。您确实需要确保输入到这些函数中的变量可以明确地类型转换为预期的数据类型。我们有一个数学函数的例子,你真的希望有一个有效的数字作为参数,而不管数据类型如何:strict_types
php > echo round("200");
200
php > echo round("200 12");
Warning: Uncaught TypeError: round():
Argument #1 ($num) must be of type int|float, string given
在这里,字符串起作用,因为它是一个明确的数字。但是,不会,因为它是模棱两可的。假设你投射它:"200"
"200 12"
php > echo (int) "200 12";
200
你变成了.这是你所期望的吗?再:"200 12"
(int) 200
php > echo (float) "gummy bears";
0
php > echo 200 + "1";
201
php > echo 200 - "gummy bears" + "1";
Warning: Uncaught TypeError: Unsupported operand types: int - string
这些是早期版本的PHP中会通过的异常评估,我们现在得到的是一种祝福。变量只能无损地进行类型转换,“鲁莽”的类型转换和损坏的数据一直是无数规避错误的根源。TypeError
另请参阅: PHP 数字字符串手册 ...具体来说,关于什么可以解释为数字,什么不能解释为数字的部分。基本上,如果你的变量通过了 is_numeric(),
那么它对于数学运算来说是可以的——如果没有,你应该得到一个错误消息!以下是手册中的示例列表:
$foo = 1 + "10.5"; // $foo is float (11.5)
$foo = 1 + "-1.3e3"; // $foo is float (-1299)
$foo = 1 + "bob-1.3e3"; // TypeError as of PHP 8.0.0, $foo is integer (1) previously
$foo = 1 + "bob3"; // TypeError as of PHP 8.0.0, $foo is integer (1) previously
$foo = 1 + "10 Small Pigs"; // $foo is integer (11) and an E_WARNING is raised in PHP 8.0.0, E_NOTICE previously
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2) and an E_WARNING is raised in PHP 8.0.0, E_NOTICE previously
$foo = "10.0 pigs " + 1; // $foo is float (11) and an E_WARNING is raised in PHP 8.0.0, E_NOTICE previously
$foo = "10.0 pigs " + 1.0; // $foo is float (11) and an E_WARNING is raised in PHP 8.0.0, E_NOTICE previously
总之,你确实想在模棱两可的类型转换曾经有效的地方更新你的代码......从长远来看,与追查“自动转换”时损坏的变量值导致的异常相比,更新代码所花费的时间更少。
评论
round("200")
strict_types=1
(int)'gummy bears'
DatePeriod
抛出 PHP 7.2.18 中没有的异常。
in_array同样的问题:
$a = null;
in_array( 1, $a ); // works in php 7 -null becomes [], fails in php 8
in_array( 1, (array)$a ); // works in php 8 but we don't want to type this... autocast is what made PHP attractive in the first place.
评论
if(is_array($a)) { ... }
in_array(1, $a ?? [])
if/else
foreach($a ?? [] as $val)
if(!is_null($a)) { ... }
评论
microtime()
返回类似 .你很可能想要."0.00369800 1644622698"
microtime(true)
round("200");
将起作用,因为字符串可以强制转换为 int/float 类型。然而,类似的东西是模棱两可的。而且你确实想在模棱两可的类型转换曾经有效的地方更新你的代码......因为它会引起各种异常,随着时间的推移,追踪这些异常所需的时间将比更新代码所需的时间更长。"200"
"200 42"
round()
declare(strict_types=1);
round("200 42");
count()
DateTime
1
'abc' == 0
true