在PHP中模拟通用类

Dev*_*von 5 php generics phpdoc

我正在尝试实现处理查询的Results类。简而言之,您将具有以下功能:

function all();
function first();
function paginate(int $perPage, int $pageNo = 1);
Run Code Online (Sandbox Code Playgroud)

这很好用,问题在于当在多个不同的查询类中使用同一结果类时,IDE无法知道返回类型。例:

UserQuery->results()->all() 将返回一个用户实体数组。

UserQuery->results()->first() 将返回一个用户实体。

在某些语言中,您具有泛型,这意味着我可以只Results<User>在UserQuery类中使用,然后我的Results类可以分别返回T[]T

我的一个想法是将一个空实体作为构造函数传递给Results类,然后尝试将该属性用作返回类型,但是我无法弄清楚。有什么解决方法吗?我要解决的主要问题是IDE自动完成和分析,因此纯phpDoc解决方案非常适合我的用例。

我能想到的唯一其他解决方法是必须为每种实体类型编写一个单独的Results类,这将证明很累。

小智 5

我认为没有办法完全按照您的描述进行操作,但是在类似情况下,我建议为每种Results类型使用一个代理类,并使用phpDocumentor的@method记录正确的返回类型。该解决方案具有在任何特定于类型的结果修改和扩展中占据重要位置的附加值。这是一个例子:

abstract class Results
{
    function all(): array
    {
    }

    function first()
    {
    }

    function paginate(int $perPage, int $pageNo = 1): array
    {
    }
}

class User { }

/**
 * @method User[] all()
 * @method User first()
 * @method User[] paginate(int $perPage, int $pageNo = 1)
 */
class UserResults extends Results { }

class UserQuery
{
    /**
     * @var UserResults
     */
    private $results;

    public function __construct()
    {
        $this->results = new UserResults();
    }

    public function results(): UserResults
    {
        return $this->results;
    }
}

$userQuery = new UserQuery();
$test = $userQuery->results()->all();
Run Code Online (Sandbox Code Playgroud)

PhpStorm正确识别返回的类型