zenstruck / foundry

A model factory library for creating expressive, auto-completable, on-demand dev/test fixtures with Symfony and Doctrine.
https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html
MIT License
671 stars 75 forks source link

PHPStan complains about return type of instantiateWith in a PersistentProxyObjectFactory factory #721

Open marien-probesys opened 3 weeks ago

marien-probesys commented 3 weeks ago

Hi,

I use PHPStan to verify the typing in my application. I have an issue when using the instantiateWith() method in a PersistentProxyObjectFactory factory.

instantiateWith() is declared in the ObjectFactory and must return an object of the template class T. However, when inheriting from the PersistentProxyObjectFactory class, T becomes T&Proxy<T>. Meaning that PHPStan expects instantiateWith() to return a T&Proxy<T> object.

namespace App\Tests\Factory;

use App\Entity\MyEntity;
use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory;

/**
 * @extends PersistentProxyObjectFactory<MyEntity>
 */
final class MyEntityFactory extends PersistentProxyObjectFactory
{
    protected function initialize(): static
    {
        // The return type of instantiateWith is correct, but PHPStan expects a MyEntity&Proxy<MyEntity> and fail.
        return $this->instantiateWith(function (array $attributes, string $class): MyEntity {
            $myEntity = new MyEntity();

            // …

            return $myEntity;
        });
    }

    // …
}
nikophil commented 3 weeks ago

Hi @marien-probesys

which Foundry's (and PHPStan) version are you using? I've recently added specific phpdoc for this case

marien-probesys commented 2 weeks ago

Hi @nikophil, thanks for your answer. I'm using PHPStan 1.12.11 (the latest version of v1) and Foundry 2.2.2.

I'm sorry I made a mistake in my explanations: the problem is not with the instantiateWith() method directly, but with its callable parameter $instantiator. It is its return type which is wrong! (so the InstantiatorCallable type defined at the top of the file)

If you need it, I can create a minimal project tomorrow in order to reproduce the problem.

marien-probesys commented 2 weeks ago

I've created a repository to reproduce the problem: https://github.com/marien-probesys/foundry-721

You can see the error here: https://github.com/marien-probesys/foundry-721/actions/runs/11915667680/job/33206464561

And the factory: https://github.com/marien-probesys/foundry-721/blob/main/src/Factory/PostFactory.php

nikophil commented 1 week ago

thanks for your reproducer! I'll soon check this