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

Creating entities with One2One and One2Many relationships fails if one2one is before one2many #835

Open
mmarton opened this issue Feb 28, 2025 · 11 comments

Comments

@mmarton
Copy link

mmarton commented Feb 28, 2025

Good day @nikophil !

You've helped me before with my edge cases about one2one relationships in the past (#655), and I'm here again with a special case. :)

There is this special case that happens in the PersistentObjectFactory with one2one relations:

->create([$inverseField => $placeholder = (new \ReflectionClass(static::class()))->newInstanceWithoutConstructor()]);

If my entity has a one2one and a many2one this "placeholder entity" may be flushed by doctrine.
This happens when the one2one relation is defined before the one2many, making the order of keys in the default function matter.

I've created a small reproducer to this issue:
https://github.com/mmarton/foundry-entity-relations-issue

best to you

@nikophil
Copy link
Member

hey @mmarton

cool thanks for the reproducer, I'll have a look soon

did this happen in a recent version?

@mmarton
Copy link
Author

mmarton commented Feb 28, 2025

yes, everything is on the latest version.

  • foundry: 2.3.6
  • phpunit: 12.0.5
  • symfony: 7.2.4
  • doctrine orm: 3.3.2

edit: I misunderstood the question. The issue was introduced with the 2.3.0 version.

@mmarton
Copy link
Author

mmarton commented Feb 28, 2025

An extra addition to the issue:

If I move my one2one relation as the last entry of the array and call

ProductFactory::new()->withOptionalEntity['optionalentity' => OptionalEntityFactory::new()])->create()

to add a new optional relation that is not present in the default() array, then the same issue happens.

@nikophil
Copy link
Member

nikophil commented Mar 2, 2025

hey @mmarton

out of curiosity, do you use php 8.4?

For some reasons, I'm struggling to fix this in every possible combinations of "cascade persist" relationships. I think the only real complete fix will use php 8.4 proxy objects

@mmarton
Copy link
Author

mmarton commented Mar 2, 2025

Interesting. Yes the project is already on 8.4, like the reproducer I've created

@nikophil
Copy link
Member

nikophil commented Mar 2, 2025

just found a very nice workaround :)

#836

I'd be glad if you try this before we merge. I've already tested it in your reproducer, and everything works.

@mmarton
Copy link
Author

mmarton commented Mar 2, 2025

I've tested your fix, and interestingly it fixes my reproducer, but fails in my project with the same thing: it tries to save an incomplete entity. I have no idea why.

@nikophil
Copy link
Member

nikophil commented Mar 2, 2025

😬

@nikophil
Copy link
Member

nikophil commented Mar 2, 2025

I don't manage to reproduce it within our testsuite without a reproducer 😞

this problem may occur because we're flushing an extra time before, the flush of the "root" factory. Can you check if you're passing several times here although only one call to create() (or createOne(), or createMany()) was done?

@mmarton
Copy link
Author

mmarton commented Mar 2, 2025

thanks for your help.
I'll need some time to investigate further and create a new reproducer.

Here is my trace, I hope it helps something:

/var/www/html/vendor/doctrine/dbal/src/Driver/API/MySQL/ExceptionConverter.php:90
/var/www/html/vendor/doctrine/dbal/src/Connection.php:1414
/var/www/html/vendor/doctrine/dbal/src/Connection.php:1356
/var/www/html/vendor/doctrine/dbal/src/Statement.php:108
/var/www/html/vendor/doctrine/dbal/src/Statement.php:133
/var/www/html/vendor/doctrine/orm/src/Persisters/Entity/BasicEntityPersister.php:251
/var/www/html/vendor/doctrine/orm/src/UnitOfWork.php:1051
/var/www/html/vendor/doctrine/orm/src/UnitOfWork.php:400
/var/www/html/vendor/doctrine/orm/src/EntityManager.php:264
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistenceManager.php:141
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistenceManager.php:76
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistentObjectFactory.php:220
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistentProxyObjectFactory.php:41
/var/www/html/vendor/zenstruck/foundry/src/Factory.php:65
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistentProxyObjectFactory.php:50
/var/www/html/tests/Factory/EventFactory.php:109
/var/www/html/vendor/zenstruck/foundry/src/LazyValue.php:40
/var/www/html/vendor/zenstruck/foundry/src/Factory.php:216
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistentObjectFactory.php:319
/var/www/html/vendor/zenstruck/foundry/src/Factory.php:206
/var/www/html/vendor/zenstruck/foundry/src/ObjectFactory.php:56
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistentObjectFactory.php:200
/var/www/html/vendor/zenstruck/foundry/src/Persistence/PersistentProxyObjectFactory.php:41
/var/www/html/tests/Integration/MyTest.php:31

@nikophil
Copy link
Member

nikophil commented Mar 6, 2025

hi @mmarton

could you please test this PR again please? (CI is failing but for a totally different reason)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants