3

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.

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.