I'm retrieving a list of vehicles from the api-backend of my app using VueJS with Axios on frontend and Laravels API-Resources on the backend. I use local dynamic scopes on the Vehicle-model in order to accomplish the filtering.This all works fine.
Now I want to sort the result before it is sent to the client. Sorting the result before passing it to the VehicleCollectionResource results in an error, that several functions are not available in my VehicleResourceCollection (e.g. $this->total() or $this->count()).
Passing the the query-result to the result as shown below, the ResourceCollection receives a valid paginated collection (which is unsorted). Trying to sort the collection within the CollectionResource only sorts small part (one "page") of the whole collection.
I'm not able to make the sorting directly on the database because some of the sort-parameters require additional calculating or information from other models.
So how can I query entries from my db, sort them and then paginate them so that other the next? Do I have to implement my own pagination-logic?
My toArray-function within VehicleCollectionResource:
public function toArray($request)
{
$sortParameters = $this->sortParameters;
$collection = $this->collection->sortBy(function ($vehicle) use ($sortParameters) {
return $this->getSortingAttribute($vehicle, $sortParameters);
})->toArray();
return [
'data' => $collection,
'links' => [
'self' => 'link-value'
],
'pagination' => [
'total' => $this->total(),
'count' => $this->count(),
'per_page' => 5,
'current_page' => $this->currentPage(),
'total_pages' => $this->lastPage()
]
];
}
My ApiVehicleController (receiving the request):
public function filter(Request $request)
{
$query = Vehicle::available();
// chain scopes to the query
if ($request->has('producer') && $request->get('producer') !== null) {
$query = $query->producer([$request->get('producer')]);
}
// other scopes ...
$sortParameters = [
'sortAfter' => $request->get('sort') ?? 'priceAsc',
'mileage' => Mileage::where('id', $request->get('mileage'))->first() ?? NULL,
'months' => Month::where('id', $request->get('duration'))->first() ?? NULL,
'location' => $request->get('location')
];
// Pass result to the CollectionResource
return new VehicleCollectionResource($query->paginate(5), $sortParameters);
}
Heading over to sorting
orderByof the query before the paginate.