Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: return type resolving #57

Closed
msvrtan opened this issue Mar 11, 2019 · 8 comments
Closed

Bug: return type resolving #57

msvrtan opened this issue Mar 11, 2019 · 8 comments

Comments

@msvrtan
Copy link

msvrtan commented Mar 11, 2019

Hi,

I'we just noticed that when using 'phpstan-doctrine' extension, there is a weird behaviour/bug with findOneBy methods: doesnt report error on calling non-existing method.

As a proof of concept (not able to share project I work on): https://github.com/msvrtan/phpstan-bug`

When calling a method findOneByUuid, it doesnt understand it's getting a Customer|null back but when calling findXOneByUuid it does: https://travis-ci.com/msvrtan/phpstan-bug/jobs/183766249

I'we also created a PR msvrtan/phpstan-bug#2 that fails https://travis-ci.com/msvrtan/phpstan-bug/builds/103870199 once I remove that Repository does extend EntityRepository...

On the other hand, if I do 'inject' repository as

/* @var \Doctrine\ORM\EntityRepository<\Customer\Customer> */
private $customerRepository;

it does report ...

I know this would be a quick 'fix' to go thru codebase and add those docblocks but it still feels like unexpected behaviour

@ondrejmirtes
Copy link
Member

Hi,
thanks - I think the current behaviour is understandable and logical, although it could be improved.

When you typehint CustomerRepository, it knows that it's an object of CustomerRepository, but it doesn't know if the injected instance is supposed to be bound to a specific entity or not - you can reuse Doctrine repositories for multiple entities.

Because you define CustomerRepository::findXOneByUuid by hand, it knows the return type. It should also know the return type of findOneByUuid but that method clashes with the magic method naming convention, and since the $this->repository's entity type is unknown, it won't report anything - it basically returns mixed. But something like that is already reported in #52 (but please keep this open, I need more testcases like this :)).

If you typehint CustomerRepository<\Customer\CustomerEntity> (and provide object manager loader in the config), it will also know return type of findOneByUuid - but not thanks to your typehint in CustomerRepository, but because of Doctrine's magic method naming convention. If you declared your method as public function findOneByUuid($uuid): int, it would still think it's ?CustomerEntity. But that's already in #52 :)

The solution is to ask in a few places (like ObjectRepositoryDynamicReturnTypeExtension) to ask for the real method return typehint before inferring it's going to be ?Entity...

@ondrejmirtes
Copy link
Member

One more side-effect of not typehinting CustomerRepository<\Customer\CustomerEntity> is that it will not tell you when you're calling findOneBy* method for an unknown field :)

@ondrejmirtes
Copy link
Member

Maybe a fix is easier thank explanation :) f7ce984 Thanks!

@ondrejmirtes
Copy link
Member

@msvrtan
Copy link
Author

msvrtan commented Mar 11, 2019

Works on example repo! Will try it now on original project

@msvrtan
Copy link
Author

msvrtan commented Mar 11, 2019

OK, now it reports the problem properly! Thank you very much, I owe you some 🍽 or 🍻 next time we see each other

@ondrejmirtes
Copy link
Member

ondrejmirtes commented Mar 11, 2019 via email

@github-actions
Copy link

github-actions bot commented May 2, 2021

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants