Is it possible to specify multiple return types on PHP 7?

PhpPhp 7Type Hinting

Php Problem Overview


I have some methods that can return one of two return types. I'm using a framework utilizing MCV so refactoring these few functions in particular is not appealing.

Is it possible to declare the return type returning one or the other and failing on anything else?

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

    return SucceedObject;
}

Php Solutions


Solution 1 - Php

As of PHP 8+, you may use union types:

function test(): FailObject|SuccessObject {}

Another way, available in all versions since PHP 4, is for the two objects to share an interface. Example:

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

In this example, ReturnInterface is empty. Its mere presence supports the needed return type declaration.

You could also use a base, possibly abstract, class.


To me, for this use case, interfaces are more clear and more extensible than union types. For example, if I later want a WarnObject I need only to define it as extending ReturnInterface -- rather than going through all signatures and updating them to FailObject|SuccessObject|WarnObject.

Solution 2 - Php

As noted by bishop, there is an RFC for adding multiple return types. However, I thought I'd add that as of PHP7.1 you can now specify a nullable return type like this:

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

So this function would take in a string and by adding the question mark before int you are allowing it to return either null or an integer.

Here's a link to the documentation: http://php.net/manual/en/functions.returning-values.php

And here's a quote from that page explaining the usage: PHP 7.1 allows for void and null return types by preceding the type declaration with a ? — (e.g. function canReturnNullorString(): ?string)

Also, here's another thread that relates to this: https://stackoverflow.com/questions/33608821/nullable-return-types-in-php7

Solution 3 - Php

PHP from 7.2 onward supports the object return type

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

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

Solution 4 - Php

Since PHP 8.0 this is possible.

You can now use union types to specify this:

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

    return new Success();
}

The fact that this is possible does not mean that it is always advisable. In many (probably most) situations, using an interface (e.g. Result, which both Failure and Failure would implement) as advised in a different answer, is still much preferable.

But there are other instances where union types could make sense to an alternative to weak typing. E.g. a method that accepts both string and int, or to describe the return type of a function like stripos(), which returns int|false.

Solution 5 - Php

This ins't correct way:

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

    return SucceedObject;
}

Multiple return type is a bad practice. Good practices:

You should define a exception:

class FailObjectException extends \Exception
{
    private $exampleExtraInfo;

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

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

Now, you can define function like:

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

    return SucceedObject;
}

And use this function with try/catch:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmyolView Question on Stackoverflow
Solution 1 - PhpbishopView Answer on Stackoverflow
Solution 2 - Phpdavid.leeView Answer on Stackoverflow
Solution 3 - PhpvisualexView Answer on Stackoverflow
Solution 4 - PhpyiviView Answer on Stackoverflow
Solution 5 - PhpcalmohallagView Answer on Stackoverflow