Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat: use ghost objects for auto refresh mechanism#967

Merged
nikophil merged 2 commits into
zenstruck:feat/proxy-php84from
nikophil:feat/proxy-php84-with-ghost-objects
Aug 26, 2025
Merged

feat: use ghost objects for auto refresh mechanism#967
nikophil merged 2 commits into
zenstruck:feat/proxy-php84from
nikophil:feat/proxy-php84-with-ghost-objects

Conversation

@nikophil
Copy link
Copy Markdown
Member

@nikophil nikophil commented Aug 25, 2025

Lazy ghost do not create identity problems, so they are more suited for our purpose.

I've also added a lot of tests, based on the different errors I had when testing the feature on a real life project

@nikophil nikophil changed the title feat/proxy php84 with ghost objects feat: use ghost objects for auto refresh mechanism Aug 25, 2025
@nikophil nikophil force-pushed the feat/proxy-php84-with-ghost-objects branch from a033d3f to fdd2490 Compare August 25, 2025 15:32
* @throws RefreshObjectFailed
*/
public function refresh(object &$object, bool $force = false, bool $allowRefreshDeletedObject = false): object
public function refresh(object &$object, bool $force = false): object
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've actually reset the refresh() method to the same state than in 2.x

*
* @param T $object
*/
public function autorefresh(object $object, object $clone): void
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to split "refresh" and "autorefresh" mechanisms, because they does not involve the same problems, and the autorefresh should not manipulate the object reference (otherwise, we're exposed to identity problems)

Comment on lines +178 to +180
// the object no longer exists
Hydrator::hydrateFromOtherObject($object, $clone);
$om->detach($object);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the object no longer exist, we still need to return something, otherwise, the lazy ghost will be re-initialized as an empty shell. For this purpose we're using a clone of the object

$strategy = $this->strategyFor($object::class);
$om = $strategy->objectManagerFor($object::class);

$id = $strategy->getIdentifierValues($clone);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need the clone here, because it still has is "identifier fields" hydrated


self::assertSame('foo', $object->getProp1());

self::assertTrue($this->objectManager()->contains($object));
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is exactly the same test in ORM version, but because the document manager is not cleared when kernel.reset is triggered, this assertions is not the same

@nikophil nikophil force-pushed the feat/proxy-php84-with-ghost-objects branch from cdd4164 to fdd2490 Compare August 25, 2025 16:18
@nikophil nikophil requested a review from kbond August 25, 2025 17:10
Copy link
Copy Markdown
Member

@kbond kbond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome! I'm glad using lazy ghosts solves the identity problems.

Question about auto-refreshing:

$user = UserFactory::createOne();

// some code that manipulates the user

$this->assertSame('updated', $user->getUsername()); // auto-refresh is triggered

// some additional code that manipulates the user

$this->assertSame('updatedagain', $user->getUsername()); // is auto-refresh still triggered?

@nikophil
Copy link
Copy Markdown
Member Author

@kbond if by "code that manipulates the user", you mean a call with browser and/or console command and/or messenger, the answer is yes

I think I need to add a test for this

Comment thread src/Object/Hydrator.php
Comment on lines +150 to +165
public static function hydrateFromOtherObject(object $object, object $other): void
{
$classes = [$object::class, ...\array_values(\class_parents($object))];

$properties = [];
foreach ($classes as $class) {
$reflector = new \ReflectionClass($class);
foreach ($reflector->getProperties() as $property) {
$properties[$property->getName()] = $property->getName();
}
}

foreach ($properties as $property) {
self::set($object, $property, self::get($other, $property), catchErrors: true);
}
}
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope this code won't break too much things...

actually if it breaks, it means that the entity/object has a design problem 😅

// no identifier values means the object no longer exists
return;
}
} catch (\Throwable $e) {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like to do this, but, this was the only way to have something working in all situations, without being to tight with Doctrine

@nikophil nikophil force-pushed the feat/proxy-php84-with-ghost-objects branch from fdd2490 to 9fabc82 Compare August 26, 2025 16:32
@nikophil
Copy link
Copy Markdown
Member Author

@kbond I've added the test I was mentioning... I'm merging this PR 🎉

@nikophil nikophil merged commit 554c3a9 into zenstruck:feat/proxy-php84 Aug 26, 2025
74 checks passed
@nikophil nikophil deleted the feat/proxy-php84-with-ghost-objects branch August 26, 2025 16:43
nikophil added a commit that referenced this pull request Aug 28, 2025
* tests: improve test for auto refresh with lazy proxy

* refactor: use lazy ghost instead of lazy proxy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants