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
607 stars 62 forks source link

Attribute wrapped in a Foundry Proxy is not compatible with `Symfony\Component\VarExporter\LazyProxyTrait` #639

Closed jdecool closed 6 days ago

jdecool commented 1 week ago

This issue is extracted from https://github.com/zenstruck/foundry/issues/626

Using Foundry 2 in a project that uses the odolbeau/phone-number-bundle, I've an error trying to generate an entity using a PhoneNumber class even if the PhoneNumber isn't created through a factory.

According to this entity:

class Customer
{
    public function __construct(
        #[ORM\Column(length: 255)]
        private ?string $name = null,

        #[ORM\Column(type: PhoneNumberType::NAME)]
        private PhoneNumber $phone,
    ) {
    }
}

And this Foundry factory:

final class CustomerFactory extends PersistentProxyObjectFactory
{
    public function __construct(
        private readonly PhoneNumberUtil $phoneNumberUtil,
    ) {
        parent::__construct();
    }

    public static function class(): string
    {
        return Customer::class;
    }

    /**
     * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories
     */
    protected function defaults(): array|callable
    {
        return [
            'name' => self::faker()->text(255),
            'phone' => $this->phoneNumberUtil->parse(self::faker()->phoneNumber(), 'FR_fr'),
        ];
    }
}

I've this error:

PHP Fatal error:  Declaration of Symfony\Component\VarExporter\LazyProxyTrait::__unserialize(array $data): void must be compatible with libphonenumber\PhoneNumber::__unserialize($data) in /home/jdecool/Workspace/sandbox/bug-foundry/vendor/symfony/var-exporter/LazyProxyTrait.php on line 322

Fatal error: Declaration of Symfony\Component\VarExporter\LazyProxyTrait::__unserialize(array $data): void must be compatible with libphonenumber\PhoneNumber::__unserialize($data) in /home/jdecool/Workspace/sandbox/bug-foundry/vendor/symfony/var-exporter/LazyProxyTrait.php on line 322
[critical] Fatal Compile Error: Declaration of Symfony\Component\VarExporter\LazyProxyTrait::__unserialize(array $data): void must be compatible with libphonenumber\PhoneNumber::__unserialize($data)

In LazyProxyTrait.php line 322:

  Compile Error: Declaration of Symfony\Component\VarExporter\LazyProxyTrait::__unserialize(array $data): void must be compatible with libphonenumber\PhoneNumber::__unserialize($data)

Because Foundry proxy defined a public function __unserialize(array $data): void function from Symfony\Component\VarExporter\LazyProxyTrait while the PhoneNumber class defines public function __unserialize($data): void

I've created a small project to reproduce the bug: https://github.com/jdecool/foundry-bug-demo

You just have to:

  1. composer install
  2. Run bin/console doctrine:fixtures:load -n to use the Foundry factory
nikophil commented 6 days ago

Hi @jdecool

I think the problem comes from symfony/var-exporter https://github.com/symfony/symfony/pull/57460

I'll also fix this in Foundry, we should not try to "proxify" objects that are not orm entities nor odm documents

jdecool commented 6 days ago

Thanks @nikophil

nikophil commented 6 days ago

@jdecool any chance to test this PR before I merge and release?

jdecool commented 6 days ago

I confirm it solves the problem 👍🏼

jdecool commented 6 days ago

Thanks @nikophil

nikophil commented 6 days ago

v2.0.4 released :)