web-dev-qa-db-ja.com

複数の戻り値のタイプPHP 7

2つの戻り値のいずれか-を返すことができるメソッドがいくつかあります(MCVを利用するフレームワークを使用しているため、特にこれらの少数の関数をリファクタリングすることは魅力的ではありません)

どちらか一方を返し、他で失敗する戻り値の型を宣言することは可能ですか?

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

    return SucceedObject;
}
37
myol

現在のところ、サポートされている方法は、2つのオブジェクトがインターフェースを共有することです。例:

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

この例では、ReturnInterfaceは空です。その単なる存在は、必要な戻り型宣言をサポートします。


現在、PHP internalsコミュニティは、ユニオン型について議論しています。 現在の提案が受け入れられた場合 、PHP 8+は複数の戻り値型をサポートします:

function test(): FailObject|SuccessObject {}

ただし、 以前のユニオンタイプRFCdeclinedでした。


ユニオンの種類に関係なく、インターフェイスアプローチを好みます。私にとっては、より明確で拡張性があります。後でWarnObjectが必要な場合は、すべての署名を調べてFailObject|SuccessObject|WarnObjectに更新するのではなく、単にReturnInterfaceを拡張するものとして定義する必要があります。

69
bishop

Bishopが指摘したように、複数の戻り値の型を追加するためのRFCがあります。ただし、PHP7.1の時点で、次のようにnull可能な戻り値の型を指定できるようになったと付け加えました。

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

したがって、この関数は文字列を受け取り、intの前に疑問符を追加することで、nullまたは整数を返すことができます。

ドキュメントへのリンクは次のとおりです。 http://php.net/manual/en/functions.returning-values.php

そして、そのページからの使用法を説明する引用があります:PHP 7.1では、型宣言の前に? —(たとえば、関数canReturnNullorString():?string)

また、これに関連する別のスレッドを次に示します。 PHP7のNullable戻り値型

40
david.lee

7.2以降のPHPは、オブジェクトの戻り値の型をサポートします

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

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

これは正しい方法ではありません:

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
}
0
calmohallag