正确处理PHP 7返回类型的方法

时间:2015-12-14 13:18:10

标签: php oop php-7

我正忙着创建一个应用程序,我想使用PHP 7返回类型。现在我在php.net上读到这是一个设计决定,当定义了返回类型时,不允许返回null

处理这个问题的正确方法是什么?

一个选项是try ... catch块:

public function getMyObject() : MyObject
{ 
     return null;
}

try
{
    getMyObject();
}
catch(Exception $e)
{
    //Catch the exception
}

我对此没有很好的感觉,因为我的代码将是一个巨大的尝试... catch块因为我需要为每个返回对象的方法编写一个try ... catch块。

Null Object Pattern对此很好,但我不喜欢为我的应用程序中的每个对象创建NullObject。 有没有正确的方法来做到这一点?

6 个答案:

答案 0 :(得分:27)

如果你的代码希望返回一个类的实例,在这种情况下是MyObject,但它没有,那么这确实是一个例外,应该这样处理。

但是,您应该自己抛出此异常。

public function getMyObject() : MyObject
{
    throw new MyCustomException("Cannot get my object");
}

然后您可以捕获该特定异常并相应地继续。

答案 1 :(得分:6)

  

我对此没有很好的感觉,因为我的代码将是一个巨大的try / catch块,因为我需要为每个返回对象的方法编写一个try / catch块。

替代方法(使用您的代码)将始终检查null的返回值,以避免使用null作为对象时出错。

使用异常更具表现力,并且可以及早发现错误,这是一件好事。因此,要么确保您的方法始终返回一个对象,要么在它无法履行合同时抛出异常。否则返回类型没有实际值。

答案 2 :(得分:6)

您可以使用Option数据类型。

这是一种以SomethingNothing作为包装值的类型。

您可以在PHP here中找到更详细的说明here和其中一个开放式实现

PS请不要为这种逻辑使用异常,输出参数或其他方法,这对于这项工作来说是错误的工具。

答案 3 :(得分:3)

目前这是不可能的,尽管如前所述,有些RFC可能会解决未来版本的问题。

截至目前,您的选择是:

1.从方法签名中删除返回类型:

public function getMyObject()
{ 
     return null;
}

2.Throw并捕捉异常(根据@ NiettheDarkAbsol的回答):

public function getMyObject() : MyObject
{
    throw new MyCustomException("Cannot get my object");
}

3.重构两种方法:

private $myObject;
//TODO think of a better method name
public function canGetMyObject() : bool
{
    $this->myObject = new myObject();
    return true;
}

public function getMyObject() : MyObject
{
    if(!$this->myObject){
        throw new MyCustomException("Cannot get my object");
    }
    return $this->myObject;
}

致电代码:

if($cls->canGetMyObject()){
    $myObject  = $cls->getMyObject();
}

4.使用bool返回类型和out参数:

public function tryGetMyObject(&$out) : bool
{
    $out = new myObject();
    return true;
}

致电代码:

$myObject = null;

if($cls->tryGetMyObject($myObject)){      
    $myObject->someMethod(); //$myObject is an instance of MyObject class
}

第3和第4个选项在预期空返回和frequant的情况下才真正值得考虑,因此异常的开销是一个因素。 可能你会发现这并不经常适用所有这些,例外是前进的方式

答案 4 :(得分:1)

从PHP7.1开始,您可以使用可空的返回类型:

public function getMyObject(): ?MyObject {
  return null;
}

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

答案 5 :(得分:0)

我打算要求同样的。我没有注意到这一点。

如果我有以下示例代码来按名称查找用户:

<?php

class User
{
    protected $name;

    /**
     * User constructor.
     *
     * @param $name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }

    /**
     * @return mixed
     */
    public function getName() : string
    {
        return $this->name;
    }
}


function findUserByName(string $name, array $users) : User {
    foreach ($users as $user) {
        if ($user->getName() == $name) {
            return $user;
        }
    }

    return null;
}


$users = [
    new User('John'), new User('Daniel')
];

$user = findUserByName('John', $users);

echo $user->getName()."\n";

$user2 = findUserByName('Micheal', $users);

我想告诉Php我可以获得User或null。现在我需要将它总是包装在try catch块中,在这种情况下,我没有太多意义来声明返回类型。另一方面,如果我的findUserByName函数很复杂,我可能会意外返回例如用户名而不是完整的用户对象,因此我希望定义返回类型。

我认为更合理的是为函数定义多个返回类型。有时你创建返回一个对象或对象数组的函数,定义很好,这个函数应该返回例如User或用户数组:User[]

在OP情况下(也是我的)我们可以将返回类型声明为User, null,它可以解决问题。