是否可以在 PHP7上指定多个返回类型?

我有一些方法可以返回 两种返回类型之一。我正在使用一个利用 MCV 的框架,因此重构这些少数函数并不吸引人。

有没有可能声明返回类型返回一个或另一个,并在其他任何事情上失败?

function test(): ?
{
if ($this->condition === false) {
return FailObject;
}


return SucceedObject;
}
90230 次浏览

至于 PHP8 + ,您可以使用 联合类型:

function test(): FailObject|SuccessObject {}

另一种方法是让两个对象共享一个接口,这种方法可以在 PHP4以来的所有版本中使用:

interface ReturnInterface {}
class FailObject implements ReturnInterface {}
class SuccessObject implements ReturnInterface {}
function test(): ReturnInterface {}

在这个例子中,ReturnInterface是空的,它的存在支持所需的返回类型声明。

您还可以使用基类(可能是抽象类)。


对我来说,在这个用例中,接口比联合类型更清晰,更可扩展。例如,如果我以后想要一个 WarnObject,我只需要将它定义为扩展 ReturnInterface——而不是遍历所有签名并将它们更新到 FailObject|SuccessObject|WarnObject

如 Bishop 所说,有一个用于添加多个返回类型的 RFC。然而,我想我要补充的是,从 PHP7.1开始,您现在可以像下面这样指定一个可以为空的返回类型:

function exampleFunction(string $input) : ?int
{
// Do something
}

因此,这个函数将接受一个字符串,通过在 int 之前添加问号,允许它返回 null 或整数。

下面是文档的链接: Http://php.net/manual/en/functions.returning-values.php

这里有一段引文解释了它的用法: PHP 7.1通过在类型声明之前使用一个?ーー(例如,函数 canReturn nNullorString () : ?字符串)

另外,这里还有一个与此相关的线程: PHP7中的可空返回类型

从7.2开始的 PHP 支持对象返回类型

Http://php.net/manual/en/migration72.new-features.php

function test(object $obj) : object
// return any type of object ...

这是不对的:

function test(): ?
{
if ($this->condition === false) {
return FailObject;
}


return SucceedObject;
}

多重返回类型是一种不好的做法。 好的做法:

您应该定义一个异常:

class FailObjectException extends \Exception
{
private $exampleExtraInfo;


public function __construct($exampleExtraInfo, $message)
{
parent::__construct($message);
$this->exampleExtraInfo = $exampleExtraInfo;
}


public function exampleExtraInfo(): int
{
return $this->exampleExtraInfo;
}
}

现在,您可以定义如下函数:

function test(): SucceedObject
{
if ($this->condition === false) {
throw new FailObjectException(...,...);
}


return SucceedObject;
}

在 try/catch 中使用这个函数:

try{
$succeedObject = $any->test();
} catch (FailObjectException $exception){
//do something
}

从 PHP 8.0开始。

现在可以使用联合类型来指定:

function test(): Success|Failure
{
if ($this->condition === false) {
return new Failure();
}


return new Success();
}

事实上,这是可能的 并不意味着它总是明智的。在许多(可能是大多数)情况下,按照不同答案中的建议,使用接口(例如 ResultFailureFailure都会实现)仍然是更可取的。

但在其他情况下,联合类型可以替代弱类型。例如,一个同时接受 stringint的方法,或者描述返回 int|false的函数的返回类型,比如 stripos()