简体   繁体   中英

Make PHPStan understand Laravel Eloquent Builder query()

I am having a hard time making larastan / phpstan understand that query() should be based on Company model and not Eloquent\Model . What am I missing?

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

And this is causing this error:

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

It seems to me that this is caused by the query() method, returning an Eloquent Builder for Illuminate\Database\Eloquent\Model where I believe it should return an Eloquent Builder for App\Models\Company here.

You need to change the query method in AbstractBaseRepository to something like this:

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

because Builder class is also generic. Also PHPStan does not check the function/method bodies. So your return type needs to be accurate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM