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

Posted

技术标签:

【中文标题】PHP7:具有标量类型声明的方法拒绝键入 NULL 值,即使在弱/强制模式下也是如此【英文标题】:PHP7: Methods with a scalar type declaration refuse to type juggle NULL values, even in weak/coercive mode 【发布时间】:2018-01-17 22:00:48 【问题描述】:

php 7.0 开始,标量类型提示intfloatstringbool 可以包含在方法签名中。默认情况下,这些类型声明以弱/强制模式(或“type juggling”模式)运行。根据PHP manual:

如果可能,PHP 会将错误类型的值强制转换为预期的标量类型。例如,为期望字符串的参数提供整数的函数将获得字符串类型的变量。

但即使可以将 NULL 强制转换为整数 0,带有 int 类型提示的方法将拒绝将入站值 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

同样,即使 it is possible 将 NULL 强制转换为布尔值 false,带有 bool 类型提示的方法将拒绝将入站值 NULL 强制转换为布尔值falsefloatstring 类型提示也是如此。

这种行为似乎与 php.net 上的文档相矛盾。这是怎么回事?

【问题讨论】:

【参考方案1】:

目前没有办法允许带有标量类型提示的方法自动type juggle将入站 NULL 值添加到声明的类型。

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

新标量类型声明的弱类型检查规则大部分(强调)与扩展和内置 PHP 函数的规则相同。唯一的例外是对 NULL 的处理:为了与我们现有的类、可调用对象和数组的类型声明保持一致,默认情况下不接受 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!

【讨论】:

以上是关于PHP7:具有标量类型声明的方法拒绝键入 NULL 值,即使在弱/强制模式下也是如此的主要内容,如果未能解决你的问题,请参考以下文章

使用返回类型声明返回 NULL

PHP7:标量返回类型声明不应该接受整数吗?

标量类型与返回值类型声明

PHP7 的新增性能

PHP7新特性

PHP7的新功能