Hi,
I have an API endpoint that offers a lot of user customisable filters. One of the fields I am filtering is a virtual field calculated based on a few different fields and related fields. Rather than build this into the query I thought I’d just use CollectionInterface::filter() to match the user query. Here’s the code:
$invoices = $this->Invoices->find('filteredResults', filters: $query);
if (isset($query['status']) || isset($query['exclude'])) {
	$statusSearch = $query['status'] ?? null;
	$exclude = $query['exclude'] ?? null;
	$invoices->formatResults(function (\Cake\Collection\CollectionInterface $invoices) use ($statusSearch, $exclude) {
		return $invoices->filter(function ($invoice) use ($statusSearch, $exclude) {
			$include = $exclude ?
				!in_array($invoice->status, explode(",", $exclude)) :
				true;
			$inSearch = $statusSearch ?
				str_contains(strtolower($invoice->status_string), strtolower($statusSearch)) :
				true;
			return $include && $inSearch;
		})
			->toArray(false);
	});
}
$invoices = $this->paginate($invoices, $paginatorConfig);
$paging = $invoices->pagingParams();
So the initial issue I ran into is that filter returns a Collection, and paginate() doesn’t like that. So I wrapped it in a formatResults(), but the collection maintained the indexing of the original query result and returned a json index instead of an array (and my frontend is expecting an array).
This formatResults() with a filter() inside gets me the results I want - however the paginator remembers the original indexing of the prefiltered results… so I end up with like 3 results on page 1, 4 results on page 2, etc. instead of properly paged results.
Is there any way I can properly paginate these results? Should I just give up on using the filter and build the filter into the query?
Thanks