Skip to content

Conversation

@soyuka
Copy link

@soyuka soyuka commented Nov 29, 2025

We've the use case inside API Platform where the JsonStreamer deserializes a JSON into a Lazy Ghost as while its not consumed (streaming) we don't need to initialize this object. Therefore at some point we try to persist an uninitialized lazy ghost and it'll likely throw "column title must not be null".

    public function testPersistLazyGhost(): void 
    {
        if (PHP_VERSION_ID < 80400) {
            $this->markTestSkipped('Lazy objects are only available in PHP 8.4+.');
        }

        $initialized = false;
        $reflector = new \ReflectionClass(PersistentEntity::class);
        $lazyGhost = $reflector->newLazyGhost(function (PersistentEntity $object) use (&$initialized) {
            $initialized = true;
            $object->setName('LazyGhostInitialized');
        });

        self::assertFalse($initialized, 'Lazy ghost should not be initialized before persist.');
        $this->_em->persist($lazyGhost);
        $this->_em->flush();
        self::assertTrue($initialized, 'Lazy ghost should be initialized during flush.');
        $this->_em->clear();
        $retrievedEntity = $this->_em->find(PersistentEntity::class, $lazyGhost->getId());
        self::assertNotNull($retrievedEntity);
        self::assertEquals('LazyGhostInitialized', $retrievedEntity->name);
    }

@derrabus
Copy link
Member

derrabus commented Dec 1, 2025

@beberlei @greg0ire

I've spoken to @soyuka about this issue. The issue is that app tries to persist lazy objects as new records. Those are lazy objects that are not Doctrine proxies. Because we read the object's values through reflection, we don't initialize the objects and basically read null everywhere.

How shall we handle this? Should we attempt to detect lazy objects and initialize them?

@greg0ire
Copy link
Member

greg0ire commented Dec 2, 2025

I'm sorry but I don't think I get it.

the JsonStreamer deserializes a JSON into a Lazy Ghost as while its not consumed (streaming) we don't need to initialize this object

So you're receiving JSON from an http request and stream that data into several entities, not all of which you persist, hence why you can't afford to initialize them?

@soyuka
Copy link
Author

soyuka commented Dec 2, 2025

I can initialize it but I was wondering if Doctrine should initialize it itself if its persisted, as right now if you attempt to persist a lazy ghost entity (that wasn't created by Doctrine) then it fails and never initializes it (as doctrine uses reflection).

@greg0ire
Copy link
Member

greg0ire commented Dec 2, 2025

I think there are at least 2 point of views:

a) If we pass an entity to the ORM, it should be able to deal with it regardless of whether it's ready or not. It shouldn't matter that the object is lazy.
b) If we pass a lazy object to the ORM, and it becomes non-lazy, that's a side effect, and it's unclear whether that side effect is OK, so maybe an exception should be thrown forbidding to force users to make their objects non-lazy explicitly, outside Doctrine.

Regardless of the answer, it seems that we should attempt to detect whether objects are lazy or not. Do we have a way to do that that is reliable and where performance won't be a concern?

@derrabus
Copy link
Member

derrabus commented Dec 2, 2025

Regardless of the answer, it seems that we should attempt to detect whether objects are lazy or not. Do we have a way to do that that is reliable and where performance won't be a concern?

Yes, we can use reflection to detect a lazy object. And since we're already accessing the object's properties through reflection, one more check won't hurt, I guess.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants