返回空值与返回类型声明

20

我正在重构一个代码库,以便与PHP7一起使用,特别是实现标量类型提示和返回类型提示时,遇到了一个问题。

我有一个带有某些属性的类,其中一个属性是 id。这个 id 不是必需的(你可以构造一个没有设置 id 的对象)。当创建这个类的新对象时,不设置 id,只有在将其插入到数据库中(由一个单独的映射器类)时,它才会获得一个 id。

这个映射器类需要检查对象是否已经存在于数据库中,它通过检查 id 是否设置来完成这项工作:

if(empty($exampleObject->getId())) {
    // Insert object
} else {
    // Update object
}

我正在对代码库中的每个函数应用返回类型提示,问题在于函数getId()如果我强制使用一个int返回类型,则不能返回NULL。即使没有启用严格类型检查,在没有严格类型检查的情况下仍会出现TypeError错误:

Fatal error: Uncaught TypeError: ExampleClass::getId()的返回值必须是整数类型,返回了null

我考虑不为此getter设置返回类型提示,但我后来意识到问题可能不是返回类型提示,而是我使用混合返回类型。我记得在某处读到使用混合返回类型是一件糟糕的事情,但我不知道如何在不使用混合返回类型的情况下解决这个问题。我可以:

  • 在getter中抛出异常,并在映射器类中设计检查,以捕获那个异常。
  • 捕获TypeError异常,并使用它表示id未设置。
  • 将id属性公开,以便我可以直接调用isset
  • 添加一个不同的方法hasId() return isset($this->id)

实际上,我并不真正喜欢这些解决方案,我想知道是否有更好的选择。像这种情况的最佳实践是什么?

此外,如果我没有启用严格类型检查,我应该只会得到一个TypeError吗?我记得PHP7默认为“弱类型提示”。


1
尝试使用 int? 作为返回类型。 - tkausl
2
@tkausl 这个实现了吗?我不知道这个功能(在PHP文档中没有),但我找到了这个RFC(可空类型)。这是你所指的吗?如果是,这是一个针对PHP 7.1的草案。 - Compizfox
哦..我确定我在某个地方看到过这个,但不确定在哪里,抱歉。 - tkausl
@tkausl,这是C#语法! - max
回复:在严格类型模式下仅收到TypeError,这并不完全正确。PHP默认情况下会尝试在类型之间进行强制转换,但如果无法进行转换,它将抛出一个TypeError,至少对于使用PHP编写的用户函数而言是如此。然而,内置/扩展函数在非严格模式下不会引发TypeError - Andrea
2个回答

31

PHP 7.1新增了可空类型,在类型名称前加一个问号来标记返回类型可以接受该类型和null:

public function getId(): ?int {
    /* … */
}

如果您仍在使用PHP 7.0,请建议省略类型声明并使用文档块。


谢谢。这意味着返回 NULL 没有什么本质上的问题吗? - Compizfox
是的,虽然有一些避免使用“null”的论点,但它们并不普遍适用。 - Andrea
1
离题了,但我想指出PSR2规定类和方法的开括号应该在新行上 ;) - wired00
@wired00 我是一位反其道而行之的人 :p - Andrea
@Compizfox,你仍然需要通过属性声明将起始值设置为null,否则它不起作用。当我通过注入具有默认空值的参数并在未给定参数时显式地将属性设置为null时,这听起来像个笑话。 - inf3rno

0

使用 null 意味着使用面向对象的方法,因为值类型不能为 null。因此,将整数类型包装在类包装器中可能是有用的。例如,可以使用 SPL 类型中的 SplInt


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接