Skip to content

Commit c74df3f

Browse files
authored
Merge pull request #12001 from greg0ire/lazy-objects-by-default
Enable native lazy objects by default
2 parents da697f2 + f2c902e commit c74df3f

File tree

8 files changed

+65
-15
lines changed

8 files changed

+65
-15
lines changed

src/UnitOfWork.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3057,7 +3057,7 @@ public function initializeObject(object $obj): void
30573057
*/
30583058
public function isUninitializedObject(mixed $obj): bool
30593059
{
3060-
if ($this->em->getConfiguration()->isNativeLazyObjectsEnabled() && ! ($obj instanceof Collection)) {
3060+
if ($this->em->getConfiguration()->isNativeLazyObjectsEnabled() && ! ($obj instanceof Collection) && is_object($obj)) {
30613061
return $this->em->getClassMetadata($obj::class)->reflClass->isUninitializedLazyObject($obj);
30623062
}
30633063

tests/Tests/ORM/EntityManagerTest.php

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@
2525
use PHPUnit\Framework\Assert;
2626
use PHPUnit\Framework\Attributes\DataProvider;
2727
use PHPUnit\Framework\Attributes\Group;
28+
use PHPUnit\Framework\Attributes\RequiresPhp;
29+
use ReflectionClass;
2830
use ReflectionProperty;
2931
use stdClass;
30-
use Symfony\Component\VarExporter\LazyGhostTrait;
3132
use TypeError;
3233

3334
class EntityManagerTest extends OrmTestCase
@@ -180,17 +181,12 @@ public function testWrapInTransactionReThrowsThrowables(): void
180181
}
181182

182183
/** Resetting the EntityManager relies on lazy objects until https://github.com/doctrine/orm/issues/5933 is resolved */
184+
#[RequiresPhp('8.4')]
183185
public function testLazyGhostEntityManager(): void
184186
{
185-
$em = new class () extends EntityManager {
186-
use LazyGhostTrait;
187+
$reflector = new ReflectionClass(EntityManager::class);
187188

188-
public function __construct()
189-
{
190-
}
191-
};
192-
193-
$em = $em::createLazyGhost(static function ($em): void {
189+
$em = $reflector->newLazyGhost($initializer = static function (EntityManager $em): void {
194190
$r = new ReflectionProperty(EntityManager::class, 'unitOfWork');
195191
$r->setValue($em, new class () extends UnitOfWork {
196192
public function __construct()
@@ -207,7 +203,7 @@ public function clear(): void
207203
$em->close();
208204
$this->assertFalse($em->isOpen());
209205

210-
$em->resetLazyObject();
206+
$reflector->resetAsLazyGhost($em, $initializer);
211207
$this->assertTrue($em->isOpen());
212208
}
213209

tests/Tests/ORM/Functional/PropertyHooksTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Doctrine\Tests\ORM\Functional;
66

7+
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
78
use Doctrine\ORM\Mapping\MappingException;
89
use Doctrine\Tests\Models\PropertyHooks\MappingVirtualProperty;
910
use Doctrine\Tests\Models\PropertyHooks\User;
@@ -17,6 +18,10 @@ protected function setUp(): void
1718
{
1819
parent::setUp();
1920

21+
if ($this->_em->getConnection()->getDatabasePlatform() instanceof AbstractMySQLPlatform) {
22+
self::markTestSkipped('MySQL/MariaDB is case-insensitive by default, and the logic of this test relies on case sensitivity.');
23+
}
24+
2025
if (! $this->_em->getConfiguration()->isNativeLazyObjectsEnabled()) {
2126
$this->markTestSkipped('Property hooks require native lazy objects to be enabled.');
2227
}

tests/Tests/ORM/Hydration/ObjectHydratorTest.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
use Doctrine\ORM\Internal\Hydration\ObjectHydrator;
1010
use Doctrine\ORM\Mapping\ClassMetadata;
1111
use Doctrine\ORM\PersistentCollection;
12-
use Doctrine\ORM\Proxy\InternalProxy;
1312
use Doctrine\ORM\Proxy\ProxyFactory;
1413
use Doctrine\ORM\Query\ResultSetMapping;
1514
use Doctrine\Tests\Mocks\ArrayResultFactory;
@@ -1030,7 +1029,7 @@ public function testCreatesProxyForLazyLoadingWithForeignKeys(): void
10301029
'Proxies',
10311030
ProxyFactory::AUTOGENERATE_ALWAYS,
10321031
) extends ProxyFactory {
1033-
public function getProxy(string $className, array $identifier): InternalProxy
1032+
public function getProxy(string $className, array $identifier): object
10341033
{
10351034
TestCase::assertSame(ECommerceShipping::class, $className);
10361035
TestCase::assertSame(['id' => 42], $identifier);
@@ -1084,7 +1083,7 @@ public function testCreatesProxyForLazyLoadingWithForeignKeysWithAliasedProductE
10841083
'Proxies',
10851084
ProxyFactory::AUTOGENERATE_ALWAYS,
10861085
) extends ProxyFactory {
1087-
public function getProxy(string $className, array $identifier): InternalProxy
1086+
public function getProxy(string $className, array $identifier): object
10881087
{
10891088
TestCase::assertSame(ECommerceShipping::class, $className);
10901089
TestCase::assertSame(['id' => 42], $identifier);

tests/Tests/ORM/Proxy/ProxyFactoryTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ public function testSkipAbstractClassesOnGeneration(): void
120120
#[Group('DDC-2432')]
121121
public function testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized(): void
122122
{
123+
if ($this->emMock->getConfiguration()->isNativeLazyObjectsEnabled()) {
124+
self::markTestSkipped('This test is not relevant when native lazy objects are enabled');
125+
}
126+
123127
$persister = $this->getMockBuilder(BasicEntityPersister::class)
124128
->onlyMethods(['load'])
125129
->disableOriginalConstructor()
@@ -146,6 +150,10 @@ public function testFailedProxyLoadingDoesNotMarkTheProxyAsInitialized(): void
146150
#[Group('DDC-2432')]
147151
public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized(): void
148152
{
153+
if ($this->emMock->getConfiguration()->isNativeLazyObjectsEnabled()) {
154+
self::markTestSkipped('This test is not relevant when native lazy objects are enabled');
155+
}
156+
149157
$persister = $this->getMockBuilder(BasicEntityPersister::class)
150158
->onlyMethods(['load', 'getClassMetadata'])
151159
->disableOriginalConstructor()
@@ -172,6 +180,10 @@ public function testFailedProxyCloningDoesNotMarkTheProxyAsInitialized(): void
172180

173181
public function testProxyClonesParentFields(): void
174182
{
183+
if ($this->emMock->getConfiguration()->isNativeLazyObjectsEnabled()) {
184+
self::markTestSkipped('This test is not relevant when native lazy objects are enabled');
185+
}
186+
175187
$companyEmployee = new CompanyEmployee();
176188
$companyEmployee->setSalary(1000); // A property on the CompanyEmployee
177189
$companyEmployee->setName('Bob'); // A property on the parent class, CompanyPerson

tests/Tests/ORM/UnitOfWorkTest.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Doctrine\ORM\Mapping\GeneratedValue;
2121
use Doctrine\ORM\Mapping\Id;
2222
use Doctrine\ORM\Mapping\ManyToOne;
23+
use Doctrine\ORM\Mapping\MappingException;
2324
use Doctrine\ORM\Mapping\Version;
2425
use Doctrine\ORM\OptimisticLockException;
2526
use Doctrine\ORM\ORMInvalidArgumentException;
@@ -40,6 +41,7 @@
4041
use stdClass;
4142

4243
use function enum_exists;
44+
use function is_object;
4345
use function random_int;
4446
use function uniqid;
4547

@@ -278,7 +280,19 @@ public function testRejectsChangeSetComputationForObjectsWithInvalidAssociationV
278280
$user->username = 'John';
279281
$user->avatar = $invalidValue;
280282

281-
$this->expectException(ORMInvalidArgumentException::class);
283+
if (
284+
is_object($invalidValue) &&
285+
! $invalidValue instanceof ArrayCollection &&
286+
$this->_emMock->getConfiguration()->isNativeLazyObjectsEnabled()
287+
) {
288+
// in the case of stdClass, the changeset is rejected because
289+
// stdClass is not a valid entity
290+
// when using native lazy objects, this happens because UnitOfWork::isUninitializedObject()
291+
// needs to load the class metadata to do its job
292+
$this->expectException(MappingException::class);
293+
} else {
294+
$this->expectException(ORMInvalidArgumentException::class);
295+
}
282296

283297
$this->_unitOfWork->computeChangeSet($metadata, $user);
284298
}

tests/Tests/OrmFunctionalTestCase.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,13 @@ protected function getEntityManager(
941941

942942
$enableNativeLazyObjects = getenv('ENABLE_NATIVE_LAZY_OBJECTS');
943943

944+
if ($enableNativeLazyObjects === false) {
945+
// If the environment variable is not set, we default to true.
946+
// This is OK because environment variables are always strings, and
947+
// we are comparing it to a boolean.
948+
$enableNativeLazyObjects = true;
949+
}
950+
944951
if (PHP_VERSION_ID >= 80400 && $enableNativeLazyObjects) {
945952
$config->enableNativeLazyObjects(true);
946953
}

tests/Tests/TestUtil.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919
use function explode;
2020
use function fwrite;
2121
use function get_debug_type;
22+
use function getenv;
2223
use function in_array;
2324
use function sprintf;
2425
use function str_starts_with;
2526
use function strlen;
2627
use function substr;
2728

29+
use const PHP_VERSION_ID;
2830
use const STDERR;
2931

3032
/**
@@ -89,8 +91,23 @@ public static function getPrivilegedConnection(): DbalExtensions\Connection
8991

9092
public static function configureProxies(Configuration $configuration): void
9193
{
94+
$enableNativeLazyObjects = getenv('ENABLE_NATIVE_LAZY_OBJECTS');
95+
96+
if ($enableNativeLazyObjects === false) {
97+
// If the environment variable is not set, we default to true.
98+
// This is OK because environment variables are always strings, and
99+
// we are comparing it to a boolean.
100+
$enableNativeLazyObjects = true;
101+
}
102+
92103
$configuration->setProxyDir(__DIR__ . '/Proxies');
93104
$configuration->setProxyNamespace('Doctrine\Tests\Proxies');
105+
106+
if (PHP_VERSION_ID >= 80400 && $enableNativeLazyObjects) {
107+
$configuration->enableNativeLazyObjects(true);
108+
109+
return;
110+
}
94111
}
95112

96113
private static function initializeDatabase(): void

0 commit comments

Comments
 (0)