amacrobert
amacrobert

Reputation: 3169

PHPStan doesn't use custom entity repository

I am using PHPStan with its Doctrine extension.

I have a custom entity repository called App\Repository\Doctrine\UserRepository with the @extends doc block:

/**
 * @extends \Doctrine\ORM\EntityRepository<\App\Entity\User>
 */
class UserRepository extends EntityRepository implements IUserRepository
{
    public function customRepositoryMethod()
    {
        // ...
    }
}

In a controller, this code:

    public function getUserMatches(EntityManager $em)
    {
        $userRepo = $em->getRepository(\App\Entity\User::class);
        $userRepo->customRepositoryMethod();
    }

...results in this PHPStan error:

Call to an undefined method Doctrine\ORM\EntityRepository<meQ\Entity\User>::customRepositoryMethod().

Thanks to phpstan-doctrine, static analysis knows that $em->getRepository(User::class) returns a EntityRepository<User>.

However, it does not know to consider the custom repository class UserRepository as the implementation of that generic type.

How do I DocBlock the UserRepository class, or otherwise configure PHPStan, so that it interprets UserRepository as the implementation of EntityRepository<User>?

What else I've tried

I've also tried this DocBlock on UserRepository to no avail:

/**
 * @implements \Doctrine\ORM\EntityRepository<\App\Entity\User>
 */

Upvotes: 4

Views: 2869

Answers (2)

Hevyweb
Hevyweb

Reputation: 456

I think you missed this action while configuring your PHPStan: add this config to the phpstan.neon

includes:
    - vendor/phpstan/phpstan-doctrine/extension.neon
    - vendor/phpstan/phpstan-doctrine/rules.neon

Upvotes: 0

yivi
yivi

Reputation: 47630

PhpStan has no way of knowing EntityManager::getRepository() is going to return your custom method.

Either add a @var annotation right there:

/** @var UserRepository $userRepo */
$userRepo = $em->getRepository(\App\Entity\User::class);

Or better yet, just inject the UserRepository, not the whole EntityManager:

public function getUserMatches(UserRepository $userRepository)
{
   $userRepository->customRepositoryMethod();
}

The above would work with PhpStan or any static analysis tool out of the box. (And, injecting the specific repository instead of the Entity Manager is a better practice in any case).

But if not, you can always try installing the Doctrine Extensions for PHPStan, which may help the tool understand the codebase in relationship to Doctrine ORM.

If you are already using the Doctrine Extensions, note that from what I gather in the docs it's only able to extract typing if your mapping configuration is provided via annotations. If you configurate ORM mappings via XML (or YAML, in older versions of Doctrine), then I think the Extensions won't be able to extract the typing data, and the above solutions will be your only way to go.

Upvotes: 5

Related Questions