Sorting by 1 to many relations
API platform's eager loading filter (class ApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension
is transforming where clause in formed query builder. It is using the ids from formed query and then transforms the where clause into WHERE id IN()
clause, causing all eliminated sub-records to be selected again. Order by clause is left in upper-most level, causing the result set always to be sorted by all sub-records.
Example
Originally formed query (correct):
SELECT n1_.title,
n0_.id AS id_0, n0_.publication_start AS publication_start_1,
n0_.publication_end AS publication_end_2,
n0_.title_image_url AS title_image_url_3,
n0_.created_at AS created_at_4,
n0_.modified_at AS modified_at_5,
n1_.id AS id_6,
n1_.title AS title_7,
n1_.locale AS locale_8,
n1_.description AS description_9,
n1_.content AS content_10,
n0_.news_category_id AS news_category_id_11,
n0_.created_by_id AS created_by_id_12,
n0_.last_modified_by_id AS last_modified_by_id_13,
n1_.news_item_id AS news_item_id_14
FROM "newsItem" n0_
LEFT JOIN "newsContent" n1_ ON n0_.id = n1_.news_item_id
WHERE (n0_.news_category_id IN (1, 2)
OR (((n0_.publication_start IS NOT NULL AND n0_.publication_start <= '2021-06-16')
AND (n0_.publication_end IS NULL OR n0_.publication_end > '2021-01-16'))
AND n0_.news_category_id IN (1,2,3,4,5,6,7)))
AND n1_.locale = 'de'
ORDER BY n1_.title ASC;
Query transformed by FilterEagerLoadingExtension.applyToCollection()
(causing both EN and DE records to be selected again):
SELECT n0_.id AS id_0,
n0_.publication_start AS publication_start_1,
n0_.publication_end AS publication_end_2,
n0_.title_image_url AS title_image_url_3,
n0_.created_at AS created_at_4,
n0_.modified_at AS modified_at_5,
n1_.id AS id_6,
n1_.title AS title_7,
n1_.locale AS locale_8,
n1_.description AS description_9,
n1_.content AS content_10,
n0_.news_category_id AS news_category_id_11,
n0_.created_by_id AS created_by_id_12,
n0_.last_modified_by_id AS last_modified_by_id_13,
n1_.news_item_id AS news_item_id_14
FROM "newsItem" n0_
LEFT JOIN "newsContent" n1_ ON n0_.id = n1_.news_item_id
WHERE
n0_.id IN (
SELECT n2_.id
FROM "newsItem" n2_
LEFT JOIN "newsContent" n3_ ON n2_.id = n3_.news_item_id
WHERE (n2_.news_category_id IN (1, 2, 3, 4)
OR (((n2_.publication_start IS NOT NULL AND n2_.publication_start <= '2021-06-16 15:42:08')
AND (n2_.publication_end IS NULL OR n2_.publication_end > '2021-06-16 15:42:08'))
AND n2_.news_category_id IN (1, 2))) AND n3_.locale = 'de'
)
AND n0_.id IN (6, 5, 3, 1, 4, 2)
ORDER BY n1_.title ASC, n0_.id ASC
- When eager loading is completely disabled, pagination is not working.
- the class
FilterEagerLoadingExtension
cannot be overridden because it is final
AC
-
Create the class NonTransformigEagerLoadFilter
as a copy ofApiPlatform\Core\Bridge\Doctrine\Orm\Extension\FilterEagerLoadingExtension
which will do nothing inapplyToCollection
-
inject this class to be used as filter_eager_loading
(hint):
api_platform.doctrine.orm.query_extension.filter_eager_loading:
class: App\Filter\NonTransformigEagerLoadFilter
-
Tests are running -
Sorting, filtering and pagination are working
Edited by Michael Voigt