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:
- You install the phpstan-doctrine extension
- Something is an entity class and it has
repositoryClass
set in its entity metadata.