PHP7:带有标量类型声明的方法拒绝键入juggle NULL值,即使在弱/强制模式下也是如此

Nat*_*ate 4 php casting type-hinting php-7

由于PHP 7.0,标量型的提示int,float,string,和bool可包括在方法签名.默认情况下,这些类型声明以弱/强制模式(或" 类型杂耍 "模式)运行.根据PHP手册:

如果可能,PHP会将错误类型的值强制转换为预期的标量类型.例如,为需要字符串的参数赋予整数的函数将获得string类型的变量.

但即使可以将NULL强制转换为整数0,带有inttypehint 的方法也会拒绝强制NULL转换为整数0 的入站值.

<?php

class MyClass
{
    public function test(int $arg)
    {
        echo $arg;
    }
}

$obj = new MyClass();
$obj->test('123'); // 123
$obj->test(false); // 0
$obj->test(null);  // TypeError: Argument 1 passed to MyClass::test()
                   // must be of the type integer, null given
Run Code Online (Sandbox Code Playgroud)

类似地,即使可以将NULL强制转换为布尔值false,带有booltypehint 的方法也会拒绝强制NULL转换为布尔值的入站值false.同样适用于floatstring类型提示.

这种行为似乎与php.net上的文档相矛盾.这里发生了什么?

Nat*_*ate 5

目前无法允许具有标量类型提示的方法自动将juggle入站NULL值键入声明的类型.

根据负责将此功能引入PHP 7 的RFC:

新标量类型声明的弱类型检查规则大多数(强调添加)与扩展和内置PHP函数相同.唯一的例外是处理NULL:为了与我们现有的类,callables和数组的类型声明一致,默认情况下不接受NULL,除非它是一个参数并且显式地给出了默认值NULL.

但是,在以下方案中,NULL值可以接受为NULL:

<?php

class MyClass
{
    // PHP 7.0+
    public function testA(int $arg = null)
    {
        if (null === $arg) {
            echo 'The argument is NULL!';
        }
    }

    // PHP 7.1+
    // https://wiki.php.net/rfc/nullable_types
    public function testB(?int $arg)
    {
        if (null === $arg) {
            echo 'The argument is NULL!';
        }
    }
}

$obj = new MyClass();
$obj->testA(null); // The argument is NULL!
$obj->testB(null); // The argument is NULL!
Run Code Online (Sandbox Code Playgroud)