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.
CodePudding user response:
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.