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

Custom persister logic? #695

Open
mpdude opened this issue Sep 30, 2024 · 4 comments
Open

Custom persister logic? #695

mpdude opened this issue Sep 30, 2024 · 4 comments
Labels
enhancement New feature or request

Comments

@mpdude
Copy link
Contributor

mpdude commented Sep 30, 2024

I'd like to use Foundry for a legacy code base where objects are not persisted through Doctrine ORM, but other means.

Currently, my factories for such legacy model objects call $this->withoutPersisting() in their initialize() method. All clients using these factories call create() or similar and then have to take care of persisting the objects (when necessary) themselves.

Is there a standard way or hook that I could use to centralize custom persistence code in the factories?

@nikophil
Copy link
Member

nikophil commented Sep 30, 2024

Hi

Basically, what I'd do would be something like this:

abstract class LegacyObjectFactory extends ObjectFactory
{
    public function __construct(
        private LegacyPersister $legacyPersister
    ){}

    public function initialize(): static
    {
        return $this->afterInstatiate(
            function(object $data): void {$this->legacyPersister->save($data)}
        );
    }
}

Note that you won't be able to use these factories in a data provider, because they will need Symfony to be booted (using a constructor in your factory makes it a "service factory") not true anymore since https://github.com/zenstruck/foundry/releases/tag/v2.2.0

in the future, we may offer an extension point dedicated for this, but there's still work to do before that

@sirpilan
Copy link

sirpilan commented Nov 8, 2024

Got a similar problem which would be resolved by this.

I am using a prePersist EntityListener on my Entity. In my case i automatically add the current user as owner.

When creating fixtues now:

MyEntity::createOne(['owner' => SOME_OWNER])
MyEntity::createOne(['owner' => ANOTHER_OWNER])

owner will allways be overwritten in my prePersist - so i cant create fixtues i want to have.

A Custom persister-logic would help here too. Or is there another way to avoid this behavior?

@nikophil
Copy link
Member

nikophil commented Nov 8, 2024

Hi @sirpilan

maybe you can change your listener and not override when a value already exists? 😅

I'm not sure what would be the benefits of a custom persister in your case? Maybe the best option would be to be able to disable doctrine's listeners from the factories 🤔 A previous attempt exists, but the PR was never finished (and, by the way, it should now target branch 2.x, so I'm not sure something from this PR can be reused)

@sirpilan
Copy link

sirpilan commented Nov 8, 2024

maybe you can change your listener and not override when a value already exists? 😅

Well, I need the user at the entity i create explicitly here: MyEntity::createOne(['owner' => SOME_OWNER])
The prePersist listener does the overwriting i dont want. When i send values, i'd have to unset a posted value owner, so it is not set, so the prePersist listener will fill it. I'll try that, thx for the suggestion :)

I'm not sure what would be the benefits of a custom persister in your case? Maybe the best option would be to be able to

A custom persister would give me a tool to bypass the persister without changing my production code. The potential soultion above is technically code I only need so the fixtures for my tests can work, which I'd like to rather not do :D

Simply: I want the fixtures to be in the database exactly as I defined them in my tests - regardless of any doctrine listeners etc.

EDIT:
Ok i can manually disable my listener for my tests in setUp:

  $container = self::$container;
  $eventManager = $container->get('doctrine.orm.entity_manager')->getEventManager();
  $listener = $container->get(MyPrePersistListener::class);
  $eventManager->removeEventListener(['prePersist'], $listener);

This solution is "ok" in my book :D

@nikophil nikophil added the enhancement New feature or request label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

No branches or pull requests

3 participants