PHP7中的可空返回类型

202

PHP 7 引入了返回类型声明。这意味着我现在可以指示返回的值是某个类、接口、数组、可调用函数或新引入的可提示标量类型之一,就像对函数参数一样。

function returnHello(): string {
    return 'hello';
}

有时候某个值并不总是存在,因此您可能会返回某种类型的内容或null。尽管您可以通过将参数的默认值设置为nullDateTime $time = null)使其可为空,但似乎没有办法对返回类型进行这样的操作。这确实是事实吗,还是我没有找到如何做到这一点?以下方法均不起作用:

function returnHello(): string? {
    return 'hello';
}

function returnHello(): string|null {
    return 'hello';
}

9
PHP7目前不支持可空的返回类型,但是有一份RFC旨在解决这个问题,它可以在PHP 7.1中实现链接。提议中的符号表示将会是function returnString(?string $stringNull) : ?string { return $stringNull;} - Elias Van Ootegem
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Jeroen De Dauw
也许更合理的做法是使用PHP7的Trowable接口(具体来说,是扩展TypeError)。 - Elias Van Ootegem
另请参见PHP7.1上的可空类型 - Syscall
3个回答

323

现在PHP 7.1支持可空返回类型。我提供的第一个RFC是他们采用的那个:

function nullOrString(int $foo) : ?string
{
    return $foo%2 ? "odd" : null;
}

旧回答:

由于我的评论实际上是对问题的回答:

PHP 7暂时不支持可空返回类型,但有一个RFC正在处理这个问题,它旨在在PHP 7.1中实现。如果通过,语法将影响所有类型提示(包括返回类型和类型提示):

新回答: 由于我的评论实际上是针对这个问题的答案:PHP 7暂时不支持可为空的返回类型,但是有一个RFC正在处理这个问题,并计划在PHP 7.1版中推出。如果通过,该语法将影响所有类型提示(包括返回类型和类型提示)。
public function returnStringOrNull(?array $optionalArray) : ?string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

还有一个竞争的RFC要添加联合类型,它能够做相同的事情,但是看起来会不同:

public function returnStringOrNull(array|null $optionalArray) : string|null
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);//string returned here
    }
    return null;
}

然而,现在你必须写:

public function returnStringOrNull( array $optionalArray = null)
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
}
或者只返回一个空字符串,以保持与返回类型一致,并检查假值:
public function returnStringOrNull( array $optionalArray = null) : string
{
    if ($optionalArray) {
        return implode(', ', $optionalArray);
    }
    return '';
}
//call
$string = $x->returnStringOrNull();
if (!$string) {
    $string = $x->returnStringOrNull(range(1, 10));
}

5
PHP 7目前尚不支持可空返回类型,但已有一份RFC来解决这个问题。是的,就是RFC,“尚未”解决。请勿误解 - 我自PHP3时代以来一直是一位真正热爱PHP的用户,没有中断过,但当我看到所有这些RFC被拒绝了,我的印象只是“什么鬼?!” 用户们看到这种混乱,并愿意以向后兼容的方式进行清理,但他们只得到了“否定”的回答。方法命名混乱?修复对null的特殊处理?不需要。添加一个选项使所有东西区分大小写?算了吧...然后,惊讶地发现人们转而使用其他语言。 - Marcin Orlowski
1
@MarcinOrlowski:可空的返回类型提示会很有意义。我遵循了7个RFC,大部分情况下我同意他们拒绝了很多RFC。他们关注的变化不是语言本身,而是运行时和编译器。对于一些被拒绝的RFC,值得阅读讨论线程以了解为什么选择不实现这些更改(例如弃用“var”)。可惜的是,他们接受了太多的好东西(例如太空船操作符)。 - Elias Van Ootegem
@EliasVanOotegem 可空类型现在得到了适当的支持,因为7.1版本已于12月1日发布。 - lonesomeday
@lonesomeday:确实如此,我在我的回答底部添加了链接和基本示例。 - Elias Van Ootegem
mmm是更新此答案的良好类型!即PHP 7.1似乎不支持联合类型。 - Dennis
如果数组为空,那么implode函数将返回一个空字符串。因此,在这种情况下,判断语句if ($optionalArray)是不必要的。你可以直接使用return implode(', ', array($optionalArray))来确保第二个参数是一个数组。 - Alireza Fallah

74
可空类型 在 PHP 7.1 中可以使用。

以下是一个语法示例:

public function getName(): ?string
{
    return $this->name; // name can be null
}

PHP 7.1现已正式发布,您可以从PHP 7.0升级(只需要检查一些不兼容更改


22
如果没有实现"nullable",那么发布返回类型声明就是一个笑话。在实现"nullable"功能之前,返回类型是无法使用的。 - joonas.fi
2
在我看来,严格类型的返回值应该始终是该类型的,空返回不符合该契约,应该抛出异常,以更好地说明空值的原因。 - Steve Buzonas
9
如果你在一个表示人的对象上考虑一个获取年龄的方法 getAgeInYears(),那么如果这个人没有告诉我们他/她的年龄,你将如何建模?返回 null?返回 0?返回 null 在语义上意味着“我们不知道”,而 0 在语义上意味着“这个人 0 岁”。因此,我认为 getAgeInYears(): ?int 是最好的设计。抛出异常应该保留给……特殊情况。在大多数系统中,不知道一个人的年龄不应被视为特殊情况。 - joonas.fi
@joonas.fi非常正确,这是一种常见的做法。然而,您现在的实现需要知道该字段是可空的,并明确地进行相应处理。这很可能是“除了null之外都执行x”的操作,这可以很容易地使用try/catch实现。此外,如果实际上需要在该可空字段中要求一个值以继续执行,则异常很可能是更好的选择。 - Steve Buzonas
@Kamafeather 我同意业务逻辑应该决定如何处理它。然而,我坚信业务逻辑应该被隔离,并严格遵守单一职责原则。如果方法的职责是实现业务规则,那么请在那里处理它。在DAO的情况下,我建议您将null视为未知,就像SQL的行为一样。在期望值的情况下,异常具有更大的价值。您不仅可以表达值缺失,还可能表达原因。 - Steve Buzonas
显示剩余4条评论

1
它适用于任何类型。
示例:
public function getOpportunity(): ?Opportunity
{
    return $this->opportunity;
}

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