ChatGPT解决这个技术问题 Extra ChatGPT

使用类型提示时无法传递空参数

以下代码:

class Type {

}

function foo(Type $t) {

}

foo(null);

运行时失败:

PHP 致命错误:传递给 foo() 的参数 1 不能为空

为什么不允许像其他语言一样传递 null ?


S
Sean the Bean

PHP 7.1 或更新版本(2016 年 12 月 2 日发布)

您可以使用此语法将变量显式声明为 null

function foo(?Type $t) {
}

这将导致

$this->foo(new Type()); // ok
$this->foo(null); // ok
$this->foo(); // error

因此,如果您想要一个可选参数,您可以遵循约定 Type $t = null,而如果您需要让参数同时接受 null 及其类型,则可以遵循上面的示例。

您可以阅读更多here

PHP 7.0 或更早版本

您必须添加一个默认值,例如

function foo(Type $t = null) {

}

这样,您可以传递一个空值。

这在手册中有关 Type Declarations 的部分中有记录:

如果参数的默认值设置为 NULL,则声明可以接受 NULL 值。


那么为什么 null 不是 null 对象呢?
大多数语言允许 null 具有任何类型。在这种情况下。
在我看来,这是一个糟糕的语言结构。 1. 在其他语言中,null 可以是任何类型,因此在这种情况下使 null 成为有效参数。 2:Php 使用参数的默认值来指定 null 是允许的,这很模糊,即使开发人员想要强制显式传递 null,它也会使强制参数成为不可能。
我同意@Henry,此外,在看起来像可选参数之后有必需参数看起来很奇怪。
我仅在 2 上同意@Henry。关于 1,您不能将 null 传递给 function foo(Type $t) 的事实是一件非常好的事情;见Null References: The Billion Dollar Mistake
T
TheOperator

从 PHP 7.1 开始,nullable types 作为函数返回类型和参数都可用。类型 ?T 可以具有指定类型 Tnull 的值。

因此,您的函数可能如下所示:

function foo(?Type $t)
{

}

只要您可以使用 PHP 7.1,就应该优先使用这种表示法而不是 function foo(Type $t = null),因为它仍然强制调用者显式指定参数 $t 的参数。


S
SeanWM

尝试:

function foo(Type $t = null) {

}

查看PHP function arguments


我遇到的问题是它改变了函数的定义。现在参数是可选的——这并不是作者真正想要的(尽管,如果他将它传递给 null,那么它就是隐式可选的)。
F
Fabian Schmengler

正如已经提到的其他答案,这只有在您指定 null 作为默认值时才有可能。

但最干净的类型安全的面向对象解决方案是 NullObject

interface FooInterface
{
    function bar();
}
class Foo implements FooInterface
{
    public function bar()
    {
        return 'i am an object';
    }
}
class NullFoo implements FooInterface
{
    public function bar()
    {
        return 'i am null (but you still can use my interface)';
    }
}

用法:

function bar_my_foo(FooInterface $foo)
{
    if ($foo instanceof NullFoo) {
        // special handling of null values may go here
    }
    echo $foo->bar();
}

bar_my_foo(new NullFoo);

这种方法通常是不切实际的,因为您现在需要 3 个类而不是 1 个类。此外,它迫使 NullFoo 的编写者重写抽象方法,即使它们没有意义(根据 null 的定义)。
根据我的经验,如果您通常以非常严格的经典 OO 方式工作,NullObject 模式可能是实用的。在答案中,imo NullObject 模式有点被滥用,因为它特别是为了避免 if (something is null) 检查,因为 NullObject 旨在涵盖不存在值的所有行为,并且任何外部合作者都不需要感兴趣对象是否不存在(null)。
S
Syscall

自 PHP 8.0 起(2020 年 11 月 26 日发布),您也可以使用 nullable union types

这意味着您可以将 Typenull 作为参数值传递:

function foo(Type|null $param) {
    var_dump($param);
}

foo(new Type()); // ok : object(Type)#1
foo(null);       // ok : NULL

阅读有关 union types 的更多信息。


c
chispitaos

就我而言,问题是本机“修剪”功能,它不接受空值。假设您有以下代码:

if (trim($tables) != '') 
{
 //code 
} 

PHP8,也抛出这个错误;所以你必须创建一个自定义的“修剪”功能,就像这个一样,让它工作。

  public function custom_trim(?string $value)
  {
    return trim($value ?? '') ;
  } 

我真的很讨厌这种从 7.4 到 8 的变化