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

Breaking Auto-Persist if some related entity is marked as cascade persist #743

Closed
mleko64 opened this issue Dec 12, 2024 · 3 comments
Closed

Comments

@mleko64
Copy link

mleko64 commented Dec 12, 2024

Since 2.x of this bundle I noticed strange thing with Auto-Persist objects. If some related object in specific entity (for example ArticleCategory in Article entity) is marked as ORM\ManyToOne(..., cascade: ['persist']) then all another related objects in ArticleCategory will be not Auto-Persisted by Foundry.

Doctrine will generate an Exception like this:
Doctrine\ORM\ORMInvalidArgumentException: A new entity was found through the relationship 'App\Entity\ArticleCategory#createdBy' that was not configured to cascade persist operations for entity: App\Entity\User@536. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'App\Entity\User#__toString()' to get a clue.

For example:

// ArticleCategory entity
class ArticleCategory
{
   //... some other fields

   #[ORM\ManyToOne]
   private User $createdBy;
}

// Article entity
class Article
{
   //... some other fields

   #[ORM\ManyToOne(cascade: ['persist'])]
   private ArticleCategory $category;
}

// ArticleCategoryFactory factory
class ArticleCategoryFactory extends PersistentProxyObjectFactory
{
   // ...some other stuff
   protected function defaults(): array|callable
    {
        return [
            'createdBy' => UserFactory::new(),
            // ...other fields
        ];
    }
}

// ArticleFactory factory
class ArticleFactory extends PersistentProxyObjectFactory
{
   // ...some other stuff
   protected function defaults(): array|callable
    {
        return [
            'category' => ArticleCategoryFactory::new(),
            // ...other fields
        ];
    }
}

// For example in test class
$article = ArticleFactory::new()->create(); // After this will be generated error like "A new entity was found through the relationship....".

I did some digging and I noticed that the problem maybe is in PersistentObjectFactory around line 265. There is a if statment with instruction to "copy" persist behavior from one factory to other:

if ($value instanceof self && isset($this->persist)) {
   $value->persist = $this->persist; // todo - breaks immutability
}

If I'm not wrong this works like this:

  1. Normalize parameters from ArticleFactory
  2. In ArticleFactory there is a field "category" (relation)
  3. Checks if relation is cascade-persist, if yes then set persist for ArticleCategoryFactory to false (line 298 in PersistentObjectFactory)
  4. Normalize parameters from ArticleCategoryFactory
  5. In ArticleCategoryFactory there is a field createdBy (relation)
  6. Line 265 will be executed and persist-value from ArticleCategoryFactory (before setted to false) will be assigned to UserFactory

If I comment out if statment in line 265 (in PersistentObjectFactory) everything works excellent.
I don't know that is intentional behavior or some bug. On version 1.x everything works well, after upgrade to 2.x is not.

There is a Reproducer demo: https://github.com/mleko64/foundry-repro

  1. Clone
  2. Run composer install
  3. Run bin/phpunit tests/FoundryTest.php
@nikophil
Copy link
Member

Hi @mleko64

any chance you test this PR please?
I think this will fix your problem

@nikophil
Copy link
Member

I've tried your reproducer with the PR and the CI passes 🎉

the PR will be released very soon

@mleko64
Copy link
Author

mleko64 commented Dec 12, 2024

Oh sorry for late. Okey, this is great news, so, I'm waiting for the new version. Thanks for checking this!

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