Home > Net >  Typehint a property to a more specific class than the interface returned by the function used to ini
Typehint a property to a more specific class than the interface returned by the function used to ini

Time:02-15

I’m trying to up my phpstan setup to level 3, but I’m getting an error like this:

Property Something::$repository (SpecificRepository) does not accept RepositoryInterface.

On a class that looks like this:

class Something
{
    /** @var SpecificRepository */
    protected $repository;

    public function __construct(ORM $orm)
    {
        $this->orm = $orm;
        $this->repository = $orm->getRepository(Something::class);
    }
}

I understand that my ORM’s getRepository method returns RepositoryInterface because it can’t be more specific, but I need the @var typehint in order to tell my IDE tools and phpstan that in this class, $repository is more specifically a SpecificRepository. How am I supposed to do that?

CodePudding user response:

PHPStan isn't going to run your code or look at your arguments to understand that this method is going to return a specific type of object -- it's just going to look at the method's return signature. Thus, from PHPStan's point of view, it's not guaranteed that getRepository() will return an instance of SpecificRepository, which means that it's not guaranteed that $this->repository will contain an instance of SpecificRepository. However, you've attempted to tell PHPStan just that via your @var typehint -- and PHPStan is (correctly) telling you that you're mistaken. To get the benefit of IDE autocompletion on a more specific class, you could typehint the attribute to its generic interface and then write a getter class that verifies the more specific class you're expecting:

protected RepositoryInterface $repository;

protected function getSpecificRepository(): SpecificRepository
{
    if ($this->repository instanceof SpecificRepository === false) {
        throw new Exception('Expected an instance of SpecificRepository');
    }
    return $this->repository;
}

Then use $this->getSpecificRepository() in your code instead of $this->repository.

CodePudding user response:

PHPStan can understand that $em->getRepository(Something::class); returns SpecificRepository if you comply with two conditions:

  1. You install the phpstan-doctrine extension
  2. Something is an entity class and it has repositoryClass set in its entity metadata.
  • Related