我使用的是PHP 7.4.16。我在PHP文件中启用了strict_types
,认为它可以防止通过抛出TypeError
将string
参数传递给期望int
的函数。但是,函数实际上接受string
并将其强制为int
。但是,如果我在函数上放置一个返回类型提示,它将按预期工作,抛出一个TypeError
。
这对我来说没有意义,而且似乎是一个明显的不一致,可能会导致错误。有人知道为什么会这样,或者我是否做错了什么吗?
测试代码:
<?php
declare(strict_types=1);
$ids = ['1', '2', '3'];
// No error thrown, coerces string argument to int.
array_map(fn (int $id) => $id, $ids);
// Throws PHP Fatal error: Uncaught TypeError: Return value of {closure}() must be of the type int, string returned
array_map(fn ($id): int => $id, $ids);
strict_types
只影响声明它的文件中的函数调用。来自PHP文档:
注意:严格类型适用于在启用了严格类型的文件中进行的函数调用,而不适用于在该文件中声明的函数。如果未启用严格类型的文件调用了在具有严格类型文件中定义的函数,则将尊重调用方的首选项(强制类型(,并强制值。
在您的情况下,示例不是调用回调本身,而是将其作为array_map
的参数传递,这意味着无论在哪里实现函数array_map
,当array_map
调用回调时,它都优先选择强制类型。
对此,一个可能的解决方案是封装array_map
,并在声明了strict_types的文件中调用回调,例如:
<?php
declare(strict_types=1);
$ids = ['1', '2', '3'];
function strict_array_map($fn, $arr){
return array_map(fn (...$arguments) => $fn(...$arguments), $arr);
}
// Now TypeError is thrown correctly
strict_array_map(fn (int $id) => $id, $ids);
// Throws PHP Fatal error: Uncaught TypeError: Return value of {closure}() must be of the type int, string returned
strict_array_map(fn ($id): int => $id, $ids);
https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict