|
31 | 31 | use Doctrine\ORM\Mapping\ClassMetadata; |
32 | 32 | use Doctrine\ORM\Mapping\ClassMetadataInfo; |
33 | 33 | use Doctrine\ORM\Query\Expr\Join; |
| 34 | +use Doctrine\ORM\Query\Expr\Select; |
34 | 35 | use Doctrine\ORM\QueryBuilder; |
35 | 36 | use Symfony\Component\HttpFoundation\RequestStack; |
36 | 37 | use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface; |
@@ -264,7 +265,7 @@ private function joinRelations(QueryBuilder $queryBuilder, QueryNameGeneratorInt |
264 | 265 | continue; |
265 | 266 | } |
266 | 267 | } else { |
267 | | - $queryBuilder->addSelect($associationAlias); |
| 268 | + $this->addSelectOnce($queryBuilder, $associationAlias); |
268 | 269 | } |
269 | 270 |
|
270 | 271 | // Avoid recursive joins for self-referencing relations |
@@ -296,7 +297,7 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a |
296 | 297 | $entityManager = $queryBuilder->getEntityManager(); |
297 | 298 | $targetClassMetadata = $entityManager->getClassMetadata($entity); |
298 | 299 | if (!empty($targetClassMetadata->subClasses)) { |
299 | | - $queryBuilder->addSelect($associationAlias); |
| 300 | + $this->addSelectOnce($queryBuilder, $associationAlias); |
300 | 301 |
|
301 | 302 | return; |
302 | 303 | } |
@@ -335,6 +336,17 @@ private function addSelect(QueryBuilder $queryBuilder, string $entity, string $a |
335 | 336 | $queryBuilder->addSelect(sprintf('partial %s.{%s}', $associationAlias, implode(',', $select))); |
336 | 337 | } |
337 | 338 |
|
| 339 | + private function addSelectOnce($queryBuilder, $alias) |
| 340 | + { |
| 341 | + $existingSelects = array_reduce($queryBuilder->getDQLPart('select') ?? [], function ($existing, $dqlSelect) { |
| 342 | + return ($dqlSelect instanceof Select) ? array_merge($existing, $dqlSelect->getParts()) : $existing; |
| 343 | + }, []); |
| 344 | + |
| 345 | + if (!\in_array($alias, $existingSelects, true)) { |
| 346 | + $queryBuilder->addSelect($alias); |
| 347 | + } |
| 348 | + } |
| 349 | + |
338 | 350 | /** |
339 | 351 | * Gets the serializer context. |
340 | 352 | * |
|
0 commit comments