larastan: Method calls on custom query builder to public parent methods are wrongly reported as private
- Larastan Version: 2.1.11
--levelused: 7- Pull request with failing test: <none>
Description
If one creates a trait to equip a model with a custom query builder, then methods calls on the custom query builder which are defined in Illuminate\Database\Query\Builder are wrongly reported as private.
Laravel code where the issue was found
I prepared the following GITHub repository with a minimal Laravel application: https://github.com/nagmat84/larastan-example. Step to reproduce the problem:
- Checkout the repository
- Install all dependencies via
composer install - Run PHPStan via
composer phpstan
You will get the following output
------ ----------------------------------------------------------------------------------------------------------
Line Http/Controllers/Controller.php
------ ----------------------------------------------------------------------------------------------------------
18 Call to private method whereBetween() of parent class Illuminate\Database\Eloquent\Builder<TNodeModel of
App\Models\Contracts\Node&Illuminate\Database\Eloquent\Model>.
------ ----------------------------------------------------------------------------------------------------------
However the method is not private.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 2
- Comments: 18
Fixed in #1299
I updated my example at https://github.com/nagmat84/larastan-example. It is now even more trivial and does not use any interface or any intersection type. But the errors are still there. IMHO this needs to be fixed, because it is a very typical pattern that models are augmented via traits.
That is not going to happen. Rather we migrate the whole project away from Laravel to Symfony.
Not only due to this problem at hand, but because we had a long history of fuck-ups due to Laravel’s stupid architecture. (Yes, I am aware that Laravel and Larastan are two different projects.) In the past I used Symfony for other project which had a much more complex DB model than the current Laravel project and I never ever encountered any of the many problem we already had with Laravel despite the fact that the current project is much simpler. (I don’t want to know what would have happened, if we had tried to realize the other projects in Laravel.)
So before I start duplicating code and create a maintainability hell for the future, I rather take the effort to migrate the whole project.
Unfortunately, the problem is back again in https://github.com/nunomaduro/larastan/pull/1285 after I have added a test class for custom relations.
I can confirm that #1299 fixed it, see here https://github.com/nagmat84/larastan-example/runs/7161581815?check_suite_focus=true.
I will now use what I have learned (i.e. that you must not rename the template parameter!) and apply it to our actual code. May be there are still other problems, but that another issue then.
Is there any chance that #1299 gets back-ported to Larastan 1.x. Our project is still stuck at Laravel 8 due to various reasons.
Sorry, for that. I pushed an even smaller MWE after @szepeviktor suggested in his post that the intersection types might be the problem (even though he wrongly called them union types). In doing the original error changed from “call to private method” into “call to undefined method”.
I followed your advices (see below) and also reverted the example repo to the full example (note that the default branch has changed).
Great. This did not only solve the problem “call to undefined method” for the branch
trivial_example, but also solved the problem “call to private method” for the branchfull_exampleand any other error. Now, PhpStan is even happy with the intersection types.I don’t understand why one must not rename the template parameter, but I can live with that restriction. IMHO, there should be a bold, eye-catching warning in the documentation that one must not rename inherited template parameters.
Yes, this is the only error which also remains for the branch
full_example. It would be nice to get a fix for that.