Eloquent Pagination and Map — not the bestest of friends
Eloquent can make things really easy. But sometimes that thing is shooting yourself in the foot with a performance problem.
We recently released an API endpoint to a customer that was paginated. The first version of the code looked something like this.
<pre class="wp-block-code">```
return $model
->relationship
->map(function ($relation) {
// tonne of heavy lifting
})
->paginate();
It is nothing crazy — just manipulate the objects in the relationship and send it on its way back to the caller. Tests all passed and things were great.
Until it was deployed into production and it took almost 3 minutes to run.
What was happening was that it was doing the ‘tonne of heavy lifting’ against all 3000 models and then returning the page that was requested. That’s not quite efficient.
The solution is to flip things around and paginate first and then the map.
``` $items = $model ->relationship ->paginate(); $mapped = $items ->getCollection() ->map(function ($relation) { // a tonne of heavy lifting }); $items->setCollection($mapped); return $items; ``` ``` By mapping only the things in the requested pagination page, the time dropped by around 85%. Needless to say, we’ve stopped using the map-then-paginate pattern in our application … and you likely should as well.