Skip to content

Commit d99f6cb

Browse files
committed
Use a WeakMap to track generated lazy objects
1 parent 5373c40 commit d99f6cb

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

lib/Doctrine/ODM/MongoDB/Proxy/Factory/NativeLazyObjectFactory.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99
use Doctrine\ODM\MongoDB\UnitOfWork;
1010
use LogicException;
1111
use ReflectionClass;
12+
use WeakMap;
1213

1314
use function count;
1415

1516
use const PHP_VERSION_ID;
1617

18+
/** @internal */
1719
class NativeLazyObjectFactory implements ProxyFactory
1820
{
21+
private static ?WeakMap $lazyObjects = null;
22+
1923
public function __construct(
2024
private readonly UnitOfWork $unitOfWork,
2125
) {
@@ -48,6 +52,30 @@ public function getProxy(ClassMetadata $metadata, $identifier): object
4852

4953
$metadata->propertyAccessors[$metadata->identifier]->setValue($proxy, $identifier);
5054

55+
if (isset(self::$lazyObjects)) {
56+
self::$lazyObjects[$proxy] = true;
57+
}
58+
5159
return $proxy;
5260
}
61+
62+
/** Only for internal tests */
63+
public static function enableTracking(bool $enabled = true): void
64+
{
65+
if ($enabled) {
66+
self::$lazyObjects ??= new WeakMap();
67+
} else {
68+
self::$lazyObjects = null;
69+
}
70+
}
71+
72+
/** Only for internal tests */
73+
public static function isLazyObject(object $object): bool
74+
{
75+
if (! isset(self::$lazyObjects)) {
76+
throw new LogicException('Lazy object tracking is not enabled.');
77+
}
78+
79+
return self::$lazyObjects->offsetExists($object);
80+
}
5381
}

lib/Doctrine/ODM/MongoDB/UnitOfWork.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3089,9 +3089,9 @@ public function initializeObject(object $obj): void
30893089
public function isUninitializedObject(object $obj): bool
30903090
{
30913091
return match (true) {
3092-
$obj instanceof InternalProxy => $obj->__isInitialized() === false,
3093-
$obj instanceof GhostObjectInterface => $obj->isProxyInitialized() === false,
3094-
$obj instanceof PersistentCollectionInterface => $obj->isInitialized() === false,
3092+
$obj instanceof InternalProxy => ! $obj->__isInitialized(),
3093+
$obj instanceof GhostObjectInterface => ! $obj->isProxyInitialized(),
3094+
$obj instanceof PersistentCollectionInterface => ! $obj->isInitialized(),
30953095
$this->dm->getConfiguration()->isNativeLazyObjectsEnabled() => $this->dm->getClassMetadata($obj::class)->reflClass->isUninitializedLazyObject($obj),
30963096
default => false
30973097
};

tests/Doctrine/ODM/MongoDB/Tests/BaseTestCase.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Doctrine\ODM\MongoDB\Configuration;
88
use Doctrine\ODM\MongoDB\DocumentManager;
99
use Doctrine\ODM\MongoDB\Mapping\Driver\AttributeDriver;
10+
use Doctrine\ODM\MongoDB\Proxy\Factory\NativeLazyObjectFactory;
1011
use Doctrine\ODM\MongoDB\Proxy\InternalProxy;
1112
use Doctrine\ODM\MongoDB\Tests\Query\Filter\Filter;
1213
use Doctrine\ODM\MongoDB\UnitOfWork;
@@ -109,6 +110,10 @@ protected static function getConfiguration(): Configuration
109110
$config->setLazyGhostObject((bool) $_ENV['USE_LAZY_GHOST_OBJECTS']);
110111
$config->enableNativeLazyObjects((bool) $_ENV['USE_NATIVE_LAZY_OBJECTS']);
111112

113+
if ($config->isNativeLazyObjectsEnabled()) {
114+
NativeLazyObjectFactory::enableTracking();
115+
}
116+
112117
$config->addFilter('testFilter', Filter::class);
113118
$config->addFilter('testFilter2', Filter::class);
114119

@@ -137,8 +142,8 @@ public static function assertArraySubset(array $subset, array $array, bool $chec
137142

138143
public static function isLazyObject(object $document): bool
139144
{
140-
if (PHP_VERSION_ID >= 80400 && (new ReflectionClass($document))->getLazyInitializer($document)) {
141-
return true;
145+
if (PHP_VERSION_ID >= 80400 && $_ENV['USE_LAZY_GHOST_OBJECTS'] ?? false) {
146+
return NativeLazyObjectFactory::isLazyObject($document);
142147
}
143148

144149
return $document instanceof InternalProxy || $document instanceof LazyLoadingInterface;

tests/Doctrine/ODM/MongoDB/Tests/Functional/Ticket/GH852Test.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use MongoDB\BSON\Binary;
1515
use PHPUnit\Framework\Attributes\DataProvider;
1616

17+
/** @see https://github.com/doctrine/mongodb-odm/pull/852 */
1718
class GH852Test extends BaseTestCase
1819
{
1920
#[DataProvider('provideIdGenerators')]

0 commit comments

Comments
 (0)