0

I'm implementing PHPStan into my application and also testing Psalm for automatic fixes, however I'm unable to make them read entity class strings (with colon) fe:

$repository = $this->em->getRepository('MyApp:EntityClass');

turns into Psalm error:

ERROR: UndefinedClass - src/Controller/MyController.php:229:48 - Class, interface or enum named MyApp:EntityClass does not exist (see https://psalm.dev/019)

and in PHP Stan

  Line   src/Controller/MyController.php                                                                                                               
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------- 
  229    Parameter #1 $className of method Doctrine\ORM\EntityManagerInterface::getRepository() expects class-string<MyApp:EntityClass>, string given.  
 ------ --------------------------------------------------------------------------------------------------------------------------------------------------- 

Easiest way to fix this is to use \EntityClass::class instead of a string 'MyApp:EntityClass' however I would like to avoid that. Probable I need to use some annotation to make both tools interprete string correctly, but I have problems figuring out which one. It would also be nice to have it avaialble globaly via entire app, and don't use annotation each time I call a class via string. Currently I've just added this error to ignored ones but would like to know how to fix that.

  • Did you try the PHPStan extension for Doctrine? The link is this: https://github.com/phpstan/phpstan-doctrine However, using `\EntityClass::class` is the best option. – Luigi C. Aug 04 '22 at 12:40
  • "Easiest way to fix this is to use \EntityClass::class instead of a string 'MyApp:EntityClass' however I would like to avoid that." why you want to avoid that? it's not the recommended way IIRC – Yassine Guedidi Aug 11 '22 at 18:56

1 Answers1

0

Easiest way to fix this is to use \EntityClass::class instead of a string 'MyApp:EntityClass' however I would like to avoid that.

You already wrote the recommended answer. Using shortname alias is deprecated since doctrine/orm v2.10. It'll probably be removed in v3.0. You should consider upgrading.

That said, this is the only sustainable solution.

$repository = $this->em->getRepository(EntityClass::class);

Install phpstan/phpstan-doctrine

Using phpstan without phpstan-doctrine is not recommended (while interpreting types of a doctrine entity). Install the phpstan extension phpstan/phpstan-doctrine and configure it. It interpretes types of QueryBuilder and Repository inside your project; like EntityManager::getReposiotry(EntityClass::class):

composer require --dev phpstan/phpstan-doctrine
# phpstan.neon
parameters:
    doctrine:
        objectManagerLoader: tests/object-manager.php

Optional: automatic refactoring

That said, you really should update your code base. To ease that process, you could use rector using the EntityAliasToClassConstantReferenceRector. Correctly configured, you're done in seconds.

composer require --dev rector/rector
// rector.php

<?php

declare(strict_types=1);

use Rector\Config\RectorConfig;
use Rector\Doctrine\Rector\MethodCall\EntityAliasToClassConstantReferenceRector;

return static function (RectorConfig $rectorConfig): void {
    $rectorConfig->phpstanConfig(__DIR__.'/phpstan.neon');

    $rectorConfig->ruleWithConfiguration(EntityAliasToClassConstantReferenceRector::class, [
        EntityAliasToClassConstantReferenceRector::ALIASES_TO_NAMESPACES => [
            'MyApp' => 'App\Entity',
        ]
    ]);
};
Michael Hirschler
  • 2,345
  • 16
  • 28