phpstan-doctrine
phpstan-doctrine copied to clipboard
support for doctrine/orm 3+?
I just upgraded orm from 2.19.0 to 3.1.0`, and as a result all of my repositories are now showing phpstan errors that this package was formerly handling, such as:
Method App\Users\Repository\UsersRolesRepository::findAll() should return array<App\Entity\UsersRoles>
but returns mixed.
This method was triggering no such error before the orm upgrade.
I've confirmed the issue also exists on the latest orm 3.0.x
I'm running:
phpstan-doctrine 1.3.62
orm 3.1.0
dbal 3.8.3
When I upgraded orm from latest 2.x to 3.0.x and 3.1.x, I got lots of errors about EntityManager methods returning mixed.
Am I missing something, or is orm3 only supported WITH dbal4?
I opened another issue before finding this one.
EDIT: bumping to dbal4 is throwing different errors now:
1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
-- --------------------------------------------------------------------------------------------------------------------------------------------
Error
-- --------------------------------------------------------------------------------------------------------------------------------------------
Internal error: Internal error: Doctrine\DBAL\Connection\StaticServerVersionProvider::__construct(): Argument #1 ($version) must be of
type string, float given, called in /app/vendor/doctrine/dbal/src/Connection.php on line 186 while
analysing file /app/src/Common/Repository/ApplicationsRepository.php
Run PHPStan with -v option and post the stack trace to:
https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml
Child process error (exit code 1):
-- --------------------------------------------------------------------------------------------------------------------------------------------
[ERROR] Found 2 errors
related to https://github.com/phpstan/phpstan-doctrine/issues/529
perhaps this is also related: https://github.com/phpstan/phpstan-doctrine/issues/308#issuecomment-1551310265
Please post the code that leads to "Method App\Users\Repository\UsersRolesRepository::findAll() should return array<App\Entity\UsersRoles>
but returns mixed.".
And please open a separate issue for the internal error, and post the stack trace as the error message instructs you to.
Sure. Again, no errors at all on orm 2.x and dbal 3.x. No other changes other than updating the doctrine packages.
[orm3/dbal3] findAll() should return array<App\Entity\UsersRoles> but returns mixed
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Applications;
use Doctrine\ORM\EntityRepository;
/** @extends EntityRepository<Applications> */
class ApplicationsRepository extends EntityRepository
{
/** @return Applications[] */
public function findAll(): array
{
return $this->getEntityManager()->createQueryBuilder()
->select('a', 'ae')
->from(Applications::class, 'a')
->leftJoin('a.expirations', 'ae')
->getQuery()
->getResult();
}
}
[orm3/dbal3] Internal error
Note: Using configuration file /app/phpstan.neon.
1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100% 1 sec
-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Error
-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Internal error: Internal error: Doctrine\DBAL\Connection\StaticServerVersionProvider::__construct(): Argument #1 ($version) must be of
type string, float given, called in /app/vendor/doctrine/dbal/src/Connection.php on line 186 while
analysing file /app/src/Common/Repository/ApplicationsRepository.php
Post the following stack trace to https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml:
## /app/vendor/doctrine/dbal/src/Connection/StaticServerVersionProvider.php(11)
#0 /app/vendor/doctrine/dbal/src/Connection.php(186):
Doctrine\DBAL\Connection\StaticServerVersionProvider->__construct()
#1 /app/vendor/doctrine/orm/src/Mapping/ClassMetadataFactory.php(724):
Doctrine\DBAL\Connection->getDatabasePlatform()
#2 /app/vendor/doctrine/orm/src/Mapping/ClassMetadataFactory.php(546):
Doctrine\ORM\Mapping\ClassMetadataFactory->getTargetPlatform()
#3 /app/vendor/doctrine/orm/src/Mapping/ClassMetadataFactory.php(174):
Doctrine\ORM\Mapping\ClassMetadataFactory->completeIdGeneratorMapping()
#4 /app/vendor/doctrine/doctrine-bundle/Mapping/ClassMetadataFactory.php(18):
Doctrine\ORM\Mapping\ClassMetadataFactory->doLoadMetadata()
#5 /app/vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php(343):
Doctrine\Bundle\DoctrineBundle\Mapping\ClassMetadataFactory->doLoadMetadata()
#6 /app/vendor/doctrine/persistence/src/Persistence/Mapping/AbstractClassMetadataFactory.php(207):
Doctrine\Persistence\Mapping\AbstractClassMetadataFactory->loadMetadata()
#7 /app/vendor/doctrine/orm/src/EntityManager.php(215):
Doctrine\Persistence\Mapping\AbstractClassMetadataFactory->getMetadataFor()
#8 /app/vendor/doctrine/orm/src/Query/Parser.php(1570):
Doctrine\ORM\EntityManager->getClassMetadata()
#9 /app/vendor/doctrine/orm/src/Query/Parser.php(1414):
Doctrine\ORM\Query\Parser->RangeVariableDeclaration()
#10 /app/vendor/doctrine/orm/src/Query/Parser.php(1183):
Doctrine\ORM\Query\Parser->IdentificationVariableDeclaration()
#11 /app/vendor/doctrine/orm/src/Query/Parser.php(769): Doctrine\ORM\Query\Parser->FromClause()
#12 /app/vendor/doctrine/orm/src/Query/Parser.php(740):
Doctrine\ORM\Query\Parser->SelectStatement()
#13 /app/vendor/doctrine/orm/src/Query/Parser.php(221): Doctrine\ORM\Query\Parser->QueryLanguage()
#14 /app/vendor/doctrine/orm/src/Query/Parser.php(309): Doctrine\ORM\Query\Parser->getAST()
#15 /app/vendor/phpstan/phpstan-doctrine/src/Type/Doctrine/Query/QueryResultTypeWalker.php(121):
Doctrine\ORM\Query\Parser->parse()
#16
/app/vendor/phpstan/phpstan-doctrine/src/Type/Doctrine/QueryBuilder/QueryBuilderGetQueryDynamicReturnTypeExtension.php(198):
PHPStan\Type\Doctrine\Query\QueryResultTypeWalker::walk()
#17
/app/vendor/phpstan/phpstan-doctrine/src/Type/Doctrine/QueryBuilder/QueryBuilderGetQueryDynamicReturnTypeExtension.php(181):
PHPStan\Type\Doctrine\QueryBuilder\QueryBuilderGetQueryDynamicReturnTypeExtension->getQueryType()
#18 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(3619):
PHPStan\Type\Doctrine\QueryBuilder\QueryBuilderGetQueryDynamicReturnTypeExtension->getTypeFromMethodCall()
#19 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1416):
PHPStan\Analyser\MutatingScope->methodCallReturnType()
#20 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(1422):
PHPStan\Analyser\MutatingScope->PHPStan\Analyser\{closure}()
#21 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(587):
PHPStan\Analyser\MutatingScope->resolveType()
#22
/app/vendor/phpstan/phpstan-doctrine/src/Type/Doctrine/QueryBuilder/ReturnQueryBuilderExpressionTypeResolverExtension.php(78):
PHPStan\Analyser\MutatingScope->getType()
#23
/app/vendor/phpstan/phpstan-doctrine/src/Type/Doctrine/QueryBuilder/ReturnQueryBuilderExpressionTypeResolverExtension.php(46):
PHPStan\Type\Doctrine\QueryBuilder\ReturnQueryBuilderExpressionTypeResolverExtension->getMethodReflection()
#24 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(605):
PHPStan\Type\Doctrine\QueryBuilder\ReturnQueryBuilderExpressionTypeResolverExtension->getType()
#25 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/MutatingScope.php(587):
PHPStan\Analyser\MutatingScope->resolveType()
#26 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Rules/FunctionReturnTypeCheck.php(52):
PHPStan\Analyser\MutatingScope->getType()
#27 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Rules/Methods/ReturnTypeRule.php(43):
PHPStan\Rules\FunctionReturnTypeCheck->checkReturnType()
#28 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(107):
PHPStan\Rules\Methods\ReturnTypeRule->processNode()
#29 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Node/ClassStatementsGatherer.php(108):
PHPStan\Analyser\FileAnalyser->PHPStan\Analyser\{closure}()
#30 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(577):
PHPStan\Node\ClassStatementsGatherer->__invoke()
#31 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(468):
PHPStan\Analyser\NodeScopeResolver::PHPStan\Analyser\{closure}()
#32 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(411):
PHPStan\Analyser\NodeScopeResolver->processStmtNode()
#33 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(576):
PHPStan\Analyser\NodeScopeResolver->processStmtNodes()
#34 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(411):
PHPStan\Analyser\NodeScopeResolver->processStmtNode()
#35 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(678):
PHPStan\Analyser\NodeScopeResolver->processStmtNodes()
#36 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(411):
PHPStan\Analyser\NodeScopeResolver->processStmtNode()
#37 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(650):
PHPStan\Analyser\NodeScopeResolver->processStmtNodes()
#38 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/NodeScopeResolver.php(380):
PHPStan\Analyser\NodeScopeResolver->processStmtNode()
#39 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Analyser/FileAnalyser.php(166):
PHPStan\Analyser\NodeScopeResolver->processNodes()
#40 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(132):
PHPStan\Analyser\FileAnalyser->analyseFile()
#41
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):
PHPStan\Command\WorkerCommand->PHPStan\Command\{closure}()
#42 phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/clue/ndjson-react/src/Decoder.php(117):
_PHPStan_cc8d35ffb\Evenement\EventEmitter->emit()
#43
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):
_PHPStan_cc8d35ffb\Clue\React\NDJson\Decoder->handleData()
#44 phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/Util.php(62):
_PHPStan_cc8d35ffb\Evenement\EventEmitter->emit()
#45
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/evenement/evenement/src/Evenement/EventEmitterTrait.php(97):
_PHPStan_cc8d35ffb\React\Stream\Util::_PHPStan_cc8d35ffb\React\Stream\{closure}()
#46
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/react/stream/src/DuplexResourceStream.php(154):
_PHPStan_cc8d35ffb\Evenement\EventEmitter->emit()
#47
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(201):
_PHPStan_cc8d35ffb\React\Stream\DuplexResourceStream->handleData()
#48
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/react/event-loop/src/StreamSelectLoop.php(173):
_PHPStan_cc8d35ffb\React\EventLoop\StreamSelectLoop->waitForStreamActivity()
#49 phar:///app/vendor/phpstan/phpstan/phpstan.phar/src/Command/WorkerCommand.php(98):
_PHPStan_cc8d35ffb\React\EventLoop\StreamSelectLoop->run()
#50
phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Command/Command.php(259):
PHPStan\Command\WorkerCommand->execute()
#51 phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(870):
_PHPStan_cc8d35ffb\Symfony\Component\Console\Command\Command->run()
#52 phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(261):
_PHPStan_cc8d35ffb\Symfony\Component\Console\Application->doRunCommand()
#53 phar:///app/vendor/phpstan/phpstan/phpstan.phar/vendor/symfony/console/Application.php(157):
_PHPStan_cc8d35ffb\Symfony\Component\Console\Application->doRun()
#54 phar:///app/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(124):
_PHPStan_cc8d35ffb\Symfony\Component\Console\Application->run()
#55 phar:///app/vendor/phpstan/phpstan/phpstan.phar/bin/phpstan(125):
_PHPStan_cc8d35ffb\{closure}()
#56 /app/vendor/phpstan/phpstan/phpstan(8): require('...')
#57 /app/vendor/bin/phpstan(119): include('...')
#58 {main}
Child process error (exit code 1):
-- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[ERROR] Found 2 errors
Used memory: 132.5 MB
if there's something you'd like me to test @ondrejmirtes, or some other info I can provide to help, just let me know.
I know it's a bit thorny to debug these more complex dependency issues remotely, since it can't be easily replicated on phpstan,org
as always, I value all of your work!
hey @ondrejmirtes, just wanted to check in on this
or perhaps the answer is, it simply isn't supported at this time (due to https://github.com/phpstan/phpstan-doctrine/issues/529)?
Hi, phpstan-doctrine fully supports ORM 3 and DBAL 4.
You're experiencing this error:
Internal error: Internal error: Doctrine\DBAL\Connection\StaticServerVersionProvider::__construct(): Argument #1 ($version) must be of type string, float given, called in /app/vendor/doctrine/dbal/src/Connection.php on line 186 while analysing file /app/src/Common/Repository/ApplicationsRepository.php
So in your case the analysis is crashing because of these lines:
https://github.com/doctrine/dbal/blob/90424473eb144659a89fb1b5c9bca37297085351/src/Connection.php#L185-L189
Meaning this is not a fault of phpstan-doctrine, but of your own Connection configuration. $this->params['serverVersion'] and $this->params['primary']['serverVersion'] need to contain a string, not a float.
Please refer to the Doctrine documentation to figure out how to configure this properly.
It's also possible this is a bug in DBAL itself.
As for:
Method App\Users\Repository\UsersRolesRepository::findAll() should return array<App\Entity\UsersRoles>
but returns mixed.
I'm not sure what goes wrong in this case. We have tests for this scenario that are passing even with ORM 3/DBAL 4.
extremely helpful, I really appreciate you taking the time to provide such a helpful response!
@ondrejmirtes I've just tested and getting the same results on orm 3.2.1 using ->serverVersion('8.0.25') in my doctrine config. Is there something I should debug/dump that would be helpful?
EDIT: this is while running dbal 3.8.6, trying 4.x now...
@ondrejmirtes I think the serverVersion issue demonstrated here, which you explained how to fix, was a red herring. This issue was suddenly triggered on dbal 4 because a new deprecation was introduced in 4 that required a verbose version number (like 1.2.3 instead o 1.2, not to mention the string vs float issue)
Once I addressed that, the original issues resurfaced, lots of expected mixed despite apparently proper configuration and no issues on orm 3.1.0/dbal 3.8.3. I am not running:
dbal 4.0.4
orm 3.2.1
phpstan-doctrine 1.4.3
Examples:
Method App\Repository\ApplicationsRepository::findAll() should return array<App\Entity\Applications> but returns mixed.
<?php
declare(strict_types=1);
namespace App\Repository;
use App\Entity\Applications;
use Doctrine\ORM\EntityRepository;
/** @extends EntityRepository<Applications> */
class ApplicationsRepository extends EntityRepository
{
/** @return Applications[] */
public function findAll(): array
{
return $this->getEntityManager()->createQueryBuilder()
->select('a', 'ae')
->from(Applications::class, 'a')
->leftJoin('a.expirations', 'ae')
->getQuery()
->getResult();
}
}
Oddly enough, it resolves this issue: https://github.com/phpstan/phpstan-doctrine/issues/525
Hey, I'm sorry, but I don't see anything actionable I could use to fix these errors. If you find the time, please submit a failing test here.