为什么 PHP 严格类型允许错误类型的函数参数?

Why does PHP strict typing allow function arguments of wrong type?

我正在使用 PHP 7.4.16。我在我的 PHP 文件中启用了 strict_types,认为它会通过抛出 TypeError 来阻止将 string 参数传递给期望 int 的函数。但是,该函数实际上接受 string 并将其强制转换为 int。但是,如果我在函数上放置一个 return 类型提示,它会按预期工作,抛出一个 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 文档:

Note: Strict typing applies to function calls made from within the file with strict typing enabled, not to the functions declared within that file. If a file without strict typing enabled makes a call to a function that was defined in a file with strict typing, the caller's preference (coercive typing) will be respected, and the value will be coerced.

在您的例子中,这些示例没有调用回调本身,而是将其作为 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