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