TYPO3 v12 QueryResultPaginator does not rebind limit/offset after QueryResult materialization
0 reputation · 10 Jul 2025, 00:49 UTC
0 reputation · 10 Jul 2025, 00:49 UTC
When using TYPO3 v12's TYPO3\CMS\Core\Pagination\QueryResultPaginator with an Extbase repository query, the goal is to paginate a large dataset efficiently by applying setLimit() and setOffset() to the underlying query before it is executed.
However, if the Extbase QueryResult has already been materialized—by iteration, toArray(), or a count() call—before the paginator sets the limit/offset, the SQL is not rebound and the paginator may return the wrong slice or the entire result set, making the pagination unreliable.
What is the correct order to instantiate the paginator relative to query execution? How can a repository guarantee that limit/offset are applied before any materialization of the QueryResult? Should a dedicated count query always be used for large tables, and if so, how should it be combined with QueryResultPaginator?
35275 reputation · 10 Jul 2025, 11:45 UTC
The paginator must be created **with the raw Extbase Query object** *before* any method that materializes the QueryResult (e.g., execute(), toArray(), iteration, or count() on the result). When the paginator receives an unexecuted query it internally rebinds setLimit() and setOffset() just before the query is run.
QueryResultPaginator with an unexecuted query causes the paginator to apply limit/offset to the underlying query before execution.->toArray(), iterating, or ->count() on the QueryResult materializes it and prevents the paginator from rebinding limit/offset.$query = $this->createQuery();$query.$paginator = \TYPO3\CMS\Core\Pagination\QueryResultPaginator::create($query, $limit, $offset);$result = $paginator->getQueryResult();$result in the Fluid template or controller.If you prefer to set limit/offset manually, do it on the query before creating the paginator:
$query->setLimit($limit)->setOffset($offset);
$paginator = \TYPO3\CMS\Core\Pagination\QueryResultPaginator::create($query);
For pagination controls you need the total number of rows. Obtain it **before** materializing the QueryResult:
$total = $query->count(); executes a lightweight COUNT query and does not affect limit/offset rebinding.$total, you can still create the paginator as shown above; the paginator will apply its own limit/offset.LocalConfiguration.php (set DEBUG or add a Doctrine SQL logger).LIMIT … OFFSET ….$limit (or fewer for the last page) and that the pagination UI shows the correct total from the separate count query.Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.