Usage of `repository()` + PHPStan makes unfixable error
Suppose:
$repo = MyFactory::repository();
$subscription = $repo->customRepoMethod($user);
Will make PHPStan screaming. So tried:
/** @var RepositoryProxy<My>|MyRepository $repo */
$repo = MyFactory::repository();
$subscription = $repo->customRepoMethod($user);
but it's no longer possible: https://phpstan.org/blog/phpstan-1-10-comes-with-lie-detector
Any idea how to solve this?
hello @er1z
do you have in your factory the phpstan-method phpdoc suggested in the doc?
there is a specific annotation for the repository() method:
/**
* @phpstan-method static RepositoryProxy<Post> repository()
*/
How does it solve the problem that I need to have signatures of proxied repository?
the phpdoc I gave you above should fix it: it gives some hints to phpstan that repository() method returns a RepositoryProxy<YourEntity>
and the RepositoryProxy is a mixin of EntityRepository so this should work
https://github.com/zenstruck/foundry/blob/1.x/src/RepositoryProxy.php#L26
Edit: for custom repo methods, maybe you can change the annotatio on phpstan-method to the one you used with @var. I've still never used phpstan with this new option, so not sure if this will work 🤔
Yes, all this issue is about custom repository methods. And it won't work anymore due to the reason described on PHPStan's website.
Now it tells that (don't remember exact error) that MyRepository is not a derivative of returned type RepositoryProxy. And the only solution is to put it into ignores.
Gonna check if annotation like this work via phpstan-method tomorrow.
Sounds like, in addition to the new phpstan mode not trusting vars, it doesn't trust mixins either.
I've made some tests here, using phpstan 1.10 + bleeding edge and everything is OK if @phpstan-method is updated to:
@phpstan-method static MyRepository&RepositoryProxy<MyEntity> repository()
this might be a lie, because that's not the real type, but phpstan does not complains about it.
(and BTW, it seems to me that @mixin is still well understood)
However, I'm wondering if we should not change the generic type of RepositoryProxy: maybe it should be
/**
* @mixin TProxiedRepository
*
* @template TProxiedObject of object
* @template TProxiedRepository of object
*/
final class RepositoryProxy implements ObjectRepository
and in the factories we should document like this:
@phpstan-method static RepositoryProxy<MyCutomRepository, MyEntity> repository()
// or, if no custom repo exists
@phpstan-method static RepositoryProxy<ObjectRepository<MyEntity>, MyEntity> repository()
WDYT?
However, I'm wondering if we should not change the generic type of RepositoryProxy: maybe it should be
If this fixes the phpstan issue I'm in favor of this. Feels less hacky than your initial solution.
Yes, but after reflexion, I'm wondering if this won't break static analysis on client side 🤔 for factories which already have the annotation... PhpStan will say the template type is not fullfilled
if this PR gets accepted, I think we should wait for it before fixing this issue
I think this problem is now solved in v2