diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 0b333e3..f6058a9 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -29,6 +29,20 @@ parameters:
identifier: 'identical.alwaysFalse'
reportUnmatched: false
path: 'src/EntityPreloader.php'
+ -
+ message: '#internal interface Doctrine\\ORM\\Mapping\\PropertyAccessors\\PropertyAccessor#' # internal, although returned from public ClassMetadata::getPropertyAccessor
+ reportUnmatched: false # only new Doctrine
+ path: 'src/EntityPreloader.php'
+ -
+ message: '#Doctrine\\ORM\\Mapping\\PropertyAccessors\\PropertyAccessor#'
+ reportUnmatched: false # only old Doctrine
+ identifier: class.notFound
+ path: 'src/EntityPreloader.php'
+ -
+ message: '#Call to function method_exists#'
+ reportUnmatched: false # only new Doctrine
+ identifier: function.alreadyNarrowedType
+ path: 'src/EntityPreloader.php'
-
message: '#Result of \|\| is always false#'
identifier: 'booleanOr.alwaysFalse'
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index dd725e3..6fe7de4 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -13,15 +13,21 @@
displayDetailsOnTestsThatTriggerErrors="true"
displayDetailsOnTestsThatTriggerWarnings="true"
displayDetailsOnTestsThatTriggerNotices="true"
+ displayDetailsOnTestsThatTriggerDeprecations="true"
cacheDirectory="cache/phpunit"
>
+
+
+
+
+
tests
-
+
src
diff --git a/src/EntityPreloader.php b/src/EntityPreloader.php
index 0d7143e..e010de6 100644
--- a/src/EntityPreloader.php
+++ b/src/EntityPreloader.php
@@ -5,6 +5,7 @@
use ArrayAccess;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
+use Doctrine\ORM\Mapping\PropertyAccessors\PropertyAccessor;
use Doctrine\ORM\PersistentCollection;
use Doctrine\ORM\QueryBuilder;
use LogicException;
@@ -14,6 +15,7 @@
use function count;
use function get_parent_class;
use function is_a;
+use function method_exists;
/**
* @template E of object
@@ -120,10 +122,10 @@ private function loadProxies(
int $maxFetchJoinSameFieldCount,
): array
{
- $identifierReflection = $classMetadata->getSingleIdReflectionProperty(); // e.g. Order::$id reflection
+ $identifierAccessor = $this->getSingleIdPropertyAccessor($classMetadata); // e.g. Order::$id reflection
$identifierName = $classMetadata->getSingleIdentifierFieldName(); // e.g. 'id'
- if ($identifierReflection === null) {
+ if ($identifierAccessor === null) {
throw new LogicException('Doctrine should use RuntimeReflectionService which never returns null.');
}
@@ -131,7 +133,7 @@ private function loadProxies(
$uninitializedIds = [];
foreach ($entities as $entity) {
- $entityId = $identifierReflection->getValue($entity);
+ $entityId = $identifierAccessor->getValue($entity);
$entityKey = (string) $entityId;
$uniqueEntities[$entityKey] = $entity;
@@ -167,11 +169,11 @@ private function preloadToMany(
int $maxFetchJoinSameFieldCount,
): array
{
- $sourceIdentifierReflection = $sourceClassMetadata->getSingleIdReflectionProperty(); // e.g. Order::$id reflection
- $sourcePropertyReflection = $sourceClassMetadata->getReflectionProperty($sourcePropertyName); // e.g. Order::$items reflection
- $targetIdentifierReflection = $targetClassMetadata->getSingleIdReflectionProperty();
+ $sourceIdentifierAccessor = $this->getSingleIdPropertyAccessor($sourceClassMetadata); // e.g. Order::$id reflection
+ $sourcePropertyAccessor = $this->getPropertyAccessor($sourceClassMetadata, $sourcePropertyName); // e.g. Order::$items reflection
+ $targetIdentifierAccessor = $this->getSingleIdPropertyAccessor($targetClassMetadata);
- if ($sourceIdentifierReflection === null || $sourcePropertyReflection === null || $targetIdentifierReflection === null) {
+ if ($sourceIdentifierAccessor === null || $sourcePropertyAccessor === null || $targetIdentifierAccessor === null) {
throw new LogicException('Doctrine should use RuntimeReflectionService which never returns null.');
}
@@ -181,9 +183,9 @@ private function preloadToMany(
$uninitializedCollections = [];
foreach ($sourceEntities as $sourceEntity) {
- $sourceEntityId = $sourceIdentifierReflection->getValue($sourceEntity);
+ $sourceEntityId = $sourceIdentifierAccessor->getValue($sourceEntity);
$sourceEntityKey = (string) $sourceEntityId;
- $sourceEntityCollection = $sourcePropertyReflection->getValue($sourceEntity);
+ $sourceEntityCollection = $sourcePropertyAccessor->getValue($sourceEntity);
if (
$sourceEntityCollection instanceof PersistentCollection
@@ -196,7 +198,7 @@ private function preloadToMany(
}
foreach ($sourceEntityCollection as $targetEntity) {
- $targetEntityKey = (string) $targetIdentifierReflection->getValue($targetEntity);
+ $targetEntityKey = (string) $targetIdentifierAccessor->getValue($targetEntity);
$targetEntities[$targetEntityKey] = $targetEntity;
}
}
@@ -213,10 +215,10 @@ private function preloadToMany(
$targetEntitiesChunk = $innerLoader(
associationMapping: $associationMapping,
sourceClassMetadata: $sourceClassMetadata,
- sourceIdentifierReflection: $sourceIdentifierReflection,
+ sourceIdentifierAccessor: $sourceIdentifierAccessor,
sourcePropertyName: $sourcePropertyName,
targetClassMetadata: $targetClassMetadata,
- targetIdentifierReflection: $targetIdentifierReflection,
+ targetIdentifierAccessor: $targetIdentifierAccessor,
uninitializedSourceEntityIdsChunk: array_values($uninitializedSourceEntityIdsChunk),
uninitializedCollections: $uninitializedCollections,
maxFetchJoinSameFieldCount: $maxFetchJoinSameFieldCount,
@@ -250,20 +252,20 @@ private function preloadToMany(
private function preloadOneToManyInner(
array|ArrayAccess $associationMapping,
ClassMetadata $sourceClassMetadata,
- ReflectionProperty $sourceIdentifierReflection,
+ PropertyAccessor|ReflectionProperty $sourceIdentifierAccessor,
string $sourcePropertyName,
ClassMetadata $targetClassMetadata,
- ReflectionProperty $targetIdentifierReflection,
+ PropertyAccessor|ReflectionProperty $targetIdentifierAccessor,
array $uninitializedSourceEntityIdsChunk,
array $uninitializedCollections,
int $maxFetchJoinSameFieldCount,
): array
{
$targetPropertyName = $sourceClassMetadata->getAssociationMappedByTargetField($sourcePropertyName); // e.g. 'order'
- $targetPropertyReflection = $targetClassMetadata->getReflectionProperty($targetPropertyName); // e.g. Item::$order reflection
+ $targetPropertyAccessor = $this->getPropertyAccessor($targetClassMetadata, $targetPropertyName); // e.g. Item::$order reflection
$targetEntities = [];
- if ($targetPropertyReflection === null) {
+ if ($targetPropertyAccessor === null) {
throw new LogicException('Doctrine should use RuntimeReflectionService which never returns null.');
}
@@ -276,11 +278,11 @@ private function preloadOneToManyInner(
);
foreach ($targetEntitiesList as $targetEntity) {
- $sourceEntity = $targetPropertyReflection->getValue($targetEntity);
- $sourceEntityKey = (string) $sourceIdentifierReflection->getValue($sourceEntity);
+ $sourceEntity = $targetPropertyAccessor->getValue($targetEntity);
+ $sourceEntityKey = (string) $sourceIdentifierAccessor->getValue($sourceEntity);
$uninitializedCollections[$sourceEntityKey]->add($targetEntity);
- $targetEntityKey = (string) $targetIdentifierReflection->getValue($targetEntity);
+ $targetEntityKey = (string) $targetIdentifierAccessor->getValue($targetEntity);
$targetEntities[$targetEntityKey] = $targetEntity;
}
@@ -302,10 +304,10 @@ private function preloadOneToManyInner(
private function preloadManyToManyInner(
array|ArrayAccess $associationMapping,
ClassMetadata $sourceClassMetadata,
- ReflectionProperty $sourceIdentifierReflection,
+ PropertyAccessor|ReflectionProperty $sourceIdentifierAccessor,
string $sourcePropertyName,
ClassMetadata $targetClassMetadata,
- ReflectionProperty $targetIdentifierReflection,
+ PropertyAccessor|ReflectionProperty $targetIdentifierAccessor,
array $uninitializedSourceEntityIdsChunk,
array $uninitializedCollections,
int $maxFetchJoinSameFieldCount,
@@ -346,7 +348,7 @@ private function preloadManyToManyInner(
}
foreach ($this->loadEntitiesBy($targetClassMetadata, $targetIdentifierName, array_values($uninitializedTargetEntityIds), $maxFetchJoinSameFieldCount) as $targetEntity) {
- $targetEntityKey = (string) $targetIdentifierReflection->getValue($targetEntity);
+ $targetEntityKey = (string) $targetIdentifierAccessor->getValue($targetEntity);
$targetEntities[$targetEntityKey] = $targetEntity;
}
@@ -379,9 +381,9 @@ private function preloadToOne(
int $maxFetchJoinSameFieldCount,
): array
{
- $sourcePropertyReflection = $sourceClassMetadata->getReflectionProperty($sourcePropertyName); // e.g. Item::$order reflection
+ $sourcePropertyAccessor = $this->getPropertyAccessor($sourceClassMetadata, $sourcePropertyName); // e.g. Item::$order reflection
- if ($sourcePropertyReflection === null) {
+ if ($sourcePropertyAccessor === null) {
throw new LogicException('Doctrine should use RuntimeReflectionService which never returns null.');
}
@@ -389,7 +391,7 @@ private function preloadToOne(
$targetEntities = [];
foreach ($sourceEntities as $sourceEntity) {
- $targetEntity = $sourcePropertyReflection->getValue($sourceEntity);
+ $targetEntity = $sourcePropertyAccessor->getValue($sourceEntity);
if ($targetEntity === null) {
continue;
@@ -483,4 +485,31 @@ private function addFetchJoinsToPreventFetchDuringHydration(
}
}
+ /**
+ * @param ClassMetadata