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

Jac*_*rez 3 php types php-7.4

我使用的是 PHP 7.4.16。我能strict_types在我的PHP文件,认为它会阻止传递string参数等一个函数int通过抛出TypeError。但是,该函数实际上接受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);
Run Code Online (Sandbox Code Playgroud)

Ale*_*uiz 5

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);
Run Code Online (Sandbox Code Playgroud)

https://www.php.net/manual/en/language.types.declarations.php#language.types.declarations.strict

  • @Jacob 这里的区别是你没有调用函数本身。您的函数正在“array_map”内部调用。如果您声明 `$callback = fn (int $id) =&gt; $id;` 并尝试在同一文件上使用 `$callback($ids[0]);` 调用它,您将触发 `strict_types`。 (2认同)
  • @AlexRuiz 应该有助于更新你的答案(最好是一个小例子) (2认同)