Имитация универсального класса в PHP - PullRequest
4 голосов
/ 03 апреля 2019

Я пытаюсь реализовать класс Results, который обрабатывает запросы. Итак, проще говоря, у вас будут такие функции:

function all();
function first();
function paginate(int $perPage, int $pageNo = 1);

Это работает довольно хорошо, проблема в том, что в IDE нет возможности узнать тип возвращаемого значения, когда один и тот же класс результатов используется в нескольких разных классах запросов. Пример:

UserQuery->results()->all() вернет массив пользовательских сущностей.

UserQuery->results()->first() вернет одну сущность пользователя.

В некоторых языках у вас есть дженерики, что означает, что я могу просто использовать Results<User> в классе UserQuery, и тогда мой класс Results может вернуть T[] и T соответственно.

У меня была одна идея - передать пустую сущность в качестве конструктора в класс Results, а затем попытаться использовать это свойство в качестве возвращаемого типа, но я не смог понять это. Есть ли обходной путь к этому? Основная проблема, которую я пытаюсь решить, - это автозаполнение и анализ IDE, поэтому чистое решение phpDoc идеально подходит для моего случая использования.

Единственный другой обходной путь, который я могу придумать, - это написать отдельный класс Results для каждого типа сущности, который окажется изнурительным.

1 Ответ

4 голосов
/ 09 апреля 2019

Я не думаю, что есть способ сделать именно то, что вы описали, но в подобных случаях я бы предложил использовать прокси-класс для каждого типа результатов и задавать правильные типы возврата, используя @ метод phpDocumentor. Это решение имеет дополнительную ценность, поскольку оно прекрасно подходит для модификаций и расширений Результатов любого типа. Вот пример:

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();

PhpStorm correctly recognises returned type

...