Skip to content

Commit 2f75535

Browse files
github-actions[bot]IonBazandependabot[bot]GromNaN
authored
Merge release 2.15.2 into 2.16.x (#2967)
* Merge pull request #2963 from IonBazan/fix-test Fix provideProxiedExprMethods provider * Bump doctrine/.github/.github/workflows/coding-standards.yml (#2941) Bumps [doctrine/.github/.github/workflows/coding-standards.yml](https://github.com/doctrine/.github) from 12.2.0 to 13.1.0. - [Release notes](https://github.com/doctrine/.github/releases) - [Commits](doctrine/.github@v12.2.0...13.1.0) --- updated-dependencies: - dependency-name: doctrine/.github/.github/workflows/coding-standards.yml dependency-version: 13.1.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Skip native lazy object initialization for unmapped properties (#2922) --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Ion Bazan <ion.bazan@gmail.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jérôme Tamarelle <jerome@tamarelle.net>
1 parent bf2e243 commit 2f75535

File tree

6 files changed

+59
-7
lines changed

6 files changed

+59
-7
lines changed

.github/workflows/coding-standards.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ on:
1111
jobs:
1212
coding-standards:
1313
name: "Coding Standards"
14-
uses: "doctrine/.github/.github/workflows/coding-standards.yml@v12.2.0"
14+
uses: "doctrine/.github/.github/workflows/coding-standards.yml@13.1.0"

docs/en/cookbook/lookup-reference.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@ need the referenced documents, you can use the ``$lookup`` stage in MongoDB's
1414
aggregation pipeline. It's similar to a SQL join, without duplication of data in
1515
the result set when there is many references to load.
1616

17+
.. note::
18+
19+
Lazy loading of references only occurs when accessing an uninitialized mapped property.
20+
If you access a property that is not mapped in Doctrine, that will not trigger
21+
loading of the referenced document.
22+
1723
Example setup
1824
-------------
1925

src/Proxy/Factory/NativeLazyObjectFactory.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
use Doctrine\Persistence\NotifyPropertyChanged;
1313
use LogicException;
1414
use ReflectionClass;
15+
use ReflectionProperty;
1516
use WeakMap;
1617

18+
use function array_key_exists;
1719
use function count;
1820

1921
use const PHP_VERSION_ID;
@@ -27,6 +29,9 @@ class NativeLazyObjectFactory implements ProxyFactory
2729
private readonly UnitOfWork $unitOfWork;
2830
private readonly LifecycleEventManager $lifecycleEventManager;
2931

32+
/** @var array<class-string, ReflectionProperty[]> */
33+
private array $skippedProperties = [];
34+
3035
public function __construct(
3136
DocumentManager $documentManager,
3237
) {
@@ -68,13 +73,40 @@ public function getProxy(ClassMetadata $metadata, $identifier): object
6873

6974
$metadata->propertyAccessors[$metadata->identifier]->setValue($proxy, $identifier);
7075

76+
foreach ($this->getSkippedProperties($metadata) as $property) {
77+
$property->skipLazyInitialization($proxy);
78+
}
79+
7180
if (isset(self::$lazyObjects)) {
7281
self::$lazyObjects[$proxy] = true;
7382
}
7483

7584
return $proxy;
7685
}
7786

87+
/** @return ReflectionProperty[] */
88+
private function getSkippedProperties(ClassMetadata $metadata): array
89+
{
90+
if (isset($this->skippedProperties[$metadata->name])) {
91+
return $this->skippedProperties[$metadata->name];
92+
}
93+
94+
$skippedProperties = [];
95+
foreach ($metadata->reflClass->getProperties() as $property) {
96+
if (array_key_exists($property->name, $metadata->propertyAccessors)) {
97+
continue;
98+
}
99+
100+
if ($property->isVirtual()) {
101+
continue;
102+
}
103+
104+
$skippedProperties[] = $property;
105+
}
106+
107+
return $this->skippedProperties[$metadata->name] = $skippedProperties;
108+
}
109+
78110
/** @internal Only for tests */
79111
public static function enableTracking(bool $enabled = true): void
80112
{

tests/Documents/DocumentWithUnmappedProperties.php

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44

55
namespace Documents;
66

7-
use Doctrine\ODM\MongoDB\Mapping\Annotations\Document;
8-
use Doctrine\ODM\MongoDB\Mapping\Annotations\Id;
7+
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
98

10-
#[Document]
9+
#[ODM\Document]
1110
class DocumentWithUnmappedProperties
1211
{
13-
#[Id]
12+
#[ODM\Id]
1413
public string $id;
1514

1615
public string $foo = 'bar';
16+
17+
// We need at least one mapped field to avoid the native lazy object to be
18+
// switched to "initialized" state immediately after setting all its properties.
19+
#[ODM\Field]
20+
public string $mappedField;
1721
}

tests/Tests/Functional/ReferencesTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Doctrine\ODM\MongoDB\Tests\BaseTestCase;
1616
use Documents\Account;
1717
use Documents\Address;
18+
use Documents\DocumentWithUnmappedProperties;
1819
use Documents\Group;
1920
use Documents\Phonenumber;
2021
use Documents\Profile;
@@ -28,6 +29,15 @@
2829

2930
class ReferencesTest extends BaseTestCase
3031
{
32+
public function testSkipInitializationForUnmappedProperties(): void
33+
{
34+
$loadedDocument = $this->dm->getReference(DocumentWithUnmappedProperties::class, '123');
35+
$this->assertInstanceOf(DocumentWithUnmappedProperties::class, $loadedDocument);
36+
37+
self::assertSame('bar', $loadedDocument->foo);
38+
self::assertTrue($this->dm->isUninitializedObject($loadedDocument));
39+
}
40+
3141
public function testManyDeleteReference(): void
3242
{
3343
$user = new User();

tests/Tests/Query/BuilderTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,8 @@ public static function provideProxiedExprMethods(): array
504504
'type()' => ['type', [7]],
505505
'all()' => ['all', [['value1', 'value2']]],
506506
'mod()' => ['mod', [2, 0]],
507-
'near()' => ['near', [1, 2], null, 5, 10],
508-
'nearSphere()' => ['nearSphere', [1, 2], null, 5, 10],
507+
'near()' => ['near', [[1, 2], null, 5, 10]],
508+
'nearSphere()' => ['nearSphere', [[1, 2], null, 5, 10]],
509509
'geoIntersects()' => ['geoIntersects', [self::createGeometry()]],
510510
'geoWithin()' => ['geoWithin', [self::createGeometry()]],
511511
'geoWithinBox()' => ['geoWithinBox', [1, 2, 3, 4]],

0 commit comments

Comments
 (0)