让 PHPStan 理解 Laravel Eloquent Builder query()

Make PHPStan understand Laravel Eloquent Builder query()

我很难让 larastan / phpstan 理解 query() 应该基于 Company 模型而不是 Eloquent\Model。我错过了什么?

<?php

namespace App\Repositories;

use App\Models\Company;

/**
 * @extends AbstractBaseRepository<Company>
 */
class CompanyRepository extends AbstractBaseRepository
{
    public function __construct()
    {
        parent::__construct(new Company());
    }

    public function firstByDomain(string $domain): ?Company
    {
        return $this->query()
            ->where('domain', $domain)
            ->first();
    }
}

<?php

namespace App\Repositories;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;

/**
 * @template TModel of Model
 */
abstract class AbstractBaseRepository
{
    /** @var TModel */
    protected $model;

    /** @param TModel $model */
    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    public function query(): Builder
    {
        return $this->model->query();
    }
}

这是导致此错误的原因:

Method App\Repositories\CompanyRepository::firstByDomain() should return App\Models\Company|null but returns Illuminate\Database\Eloquent\Model|null.

在我看来,这是由 query() 方法引起的,returning 一个 Eloquent Builder for Illuminate\Database\Eloquent\Model 我认为它应该 return 这里是 App\Models\Company 的 Eloquent 生成器。

您需要将 AbstractBaseRepository 中的 query 方法更改为如下内容:

/** @return Builder<TModel> */
public function query(): Builder
{
    return $this->model->query();
}

因为Builder class也是通用的。 PHPStan 也不检查 function/method 主体。所以你的 return 类型需要准确。