|
28 | 28 | use ApiPlatform\Exception\RuntimeException; |
29 | 29 | use ApiPlatform\Metadata\ApiProperty; |
30 | 30 | use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface; |
| 31 | +use Doctrine\ORM\Mapping\ClassMetadata; |
31 | 32 | use Doctrine\ORM\Mapping\ClassMetadataInfo; |
32 | 33 | use Doctrine\ORM\Query\Expr\Join; |
33 | 34 | use Doctrine\ORM\QueryBuilder; |
@@ -167,7 +168,7 @@ private function apply(bool $collection, QueryBuilder $queryBuilder, QueryNameGe |
167 | 168 | * |
168 | 169 | * @throws RuntimeException when the max number of joins has been reached |
169 | 170 | */ |
170 | | - private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, bool $forceEager, bool $fetchPartial, string $parentAlias, array $options = [], array $normalizationContext = [], bool $wasLeftJoin = false, int &$joinCount = 0, int $currentDepth = null) |
| 171 | + private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, bool $forceEager, bool $fetchPartial, string $parentAlias, array $options = [], array $normalizationContext = [], bool $wasLeftJoin = false, int &$joinCount = 0, int $currentDepth = null, string $parentAssociation = null) |
171 | 172 | { |
172 | 173 | if ($joinCount > $this->maxJoins) { |
173 | 174 | throw new RuntimeException('The total number of joined relations has exceeded the specified maximum. Raise the limit if necessary with the "api_platform.eager_loading.max_joins" configuration key (https://api-platform.com/docs/core/performance/#eager-loading), or limit the maximum serialization depth using the "enable_max_depth" option of the Symfony serializer (https://symfony.com/doc/current/components/serializer.html#handling-serialization-depth).'); |
@@ -232,6 +233,16 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt |
232 | 233 | continue; |
233 | 234 | } |
234 | 235 |
|
| 236 | + // Avoid joining back to the parent that we just came from, but only on *ToOne relations |
| 237 | + if ( |
| 238 | + null !== $parentAssociation && |
| 239 | + isset($mapping['inversedBy']) && |
| 240 | + $mapping['inversedBy'] === $parentAssociation && |
| 241 | + $mapping['type'] & ClassMetadata::TO_ONE |
| 242 | + ) { |
| 243 | + continue; |
| 244 | + } |
| 245 | + |
235 | 246 | $existingJoin = QueryBuilderHelper::getExistingJoin($queryBuilder, $parentAlias, $association); |
236 | 247 |
|
237 | 248 | if (null !== $existingJoin) { |
@@ -276,7 +287,7 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt |
276 | 287 | } |
277 | 288 | } |
278 | 289 |
|
279 | | - $this->joinRelations($queryBuilder, $queryNameGenerator, $mapping['targetEntity'], $forceEager, $fetchPartial, $associationAlias, $options, $childNormalizationContext, $isLeftJoin, $joinCount, $currentDepth); |
| 290 | + $this->joinRelations($queryBuilder, $queryNameGenerator, $mapping['targetEntity'], $forceEager, $fetchPartial, $associationAlias, $options, $childNormalizationContext, $isLeftJoin, $joinCount, $currentDepth, $association); |
280 | 291 | } |
281 | 292 | } |
282 | 293 |
|
|
0 commit comments