From ccc59a656ae289c3140f9d275bcc9bd801ea0fbf Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 7 Oct 2025 13:10:17 +0200 Subject: [PATCH] fix(doctrine): group or filter in an AndWhere #7441 --- src/Doctrine/Orm/Filter/FreeTextQueryFilter.php | 15 ++++++++++++++- tests/Functional/Parameters/OrFilterTest.php | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/Doctrine/Orm/Filter/FreeTextQueryFilter.php b/src/Doctrine/Orm/Filter/FreeTextQueryFilter.php index c73504c597..b773f04787 100644 --- a/src/Doctrine/Orm/Filter/FreeTextQueryFilter.php +++ b/src/Doctrine/Orm/Filter/FreeTextQueryFilter.php @@ -20,6 +20,7 @@ use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface; use ApiPlatform\Metadata\BackwardCompatibleFilterDescriptionTrait; use ApiPlatform\Metadata\Operation; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\QueryBuilder; final class FreeTextQueryFilter implements FilterInterface, ManagerRegistryAwareInterface, LoggerAwareInterface @@ -46,14 +47,26 @@ public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $q } $parameter = $context['parameter']; + $qb = clone $queryBuilder; + $qb->resetDQLPart('where'); + $qb->setParameters(new ArrayCollection()); foreach ($this->properties ?? $parameter->getProperties() ?? [] as $property) { $this->filter->apply( - $queryBuilder, + $qb, $queryNameGenerator, $resourceClass, $operation, ['parameter' => $parameter->withProperty($property)] + $context ); } + + $queryBuilder->andWhere($qb->getDQLPart('where')); + $parameters = $queryBuilder->getParameters(); + + foreach ($qb->getParameters() as $p) { + $parameters->add($p); + } + + $queryBuilder->setParameters($parameters); } } diff --git a/tests/Functional/Parameters/OrFilterTest.php b/tests/Functional/Parameters/OrFilterTest.php index 4c67a50308..ba456840de 100644 --- a/tests/Functional/Parameters/OrFilterTest.php +++ b/tests/Functional/Parameters/OrFilterTest.php @@ -20,6 +20,7 @@ use ApiPlatform\Tests\Fixtures\TestBundle\Entity\ChickenCoop; use ApiPlatform\Tests\RecreateSchemaTrait; use ApiPlatform\Tests\SetupClassResourcesTrait; +use Doctrine\Bundle\DoctrineBundle\DataCollector\DoctrineDataCollector; use Doctrine\ODM\MongoDB\MongoDBException; use PHPUnit\Framework\Attributes\DataProvider; @@ -62,6 +63,22 @@ public function testOrFilter(string $url, int $expectedCount): void $this->assertJsonContains(['totalItems' => $expectedCount]); } + public function testOrFilterWithAnd(): void + { + if ($this->isMongoDB()) { + $this->markTestSkipped(); + } + $client = self::createClient(); + $client->enableProfiler(); + $client->request('GET', '/chickens?autocomplete=978020137962&chickenCoop=/chicken_coops/2'); + $profile = $client->getProfile(); + $this->assertResponseIsSuccessful(); + + /** @var DoctrineDataCollector */ + $db = $profile->getCollector('db'); + $this->assertStringContainsString('WHERE c1_.id = ? AND (c2_.name = ? OR c2_.ean = ?))', end($db->getQueries()['default'])['sql']); + } + public static function orFilterDataProvider(): \Generator { yield 'ean through autocomplete' => [