Philipp Mochine
Philipp Mochine

Reputation: 4705

Laravel - How to manual paginate but with max number of total count?

Currently, I have a lot of Joins and SubJoins with Group By etc.

To make it short: I cannot use paginate, because it is too slow (because of Group by). That is why I need to use pagination manually, however, I need to limit the total number of rows as well. With rows way above 10k, I want to have the maximum of a total of 300!

My current approach works suboptimal and I don't really know how to fix it:

return \DB::table('offers')
           ->alotOfQueries/joins
           ->...
           ->limit(300) //we show only a maximum of 300 offers
           ->get();

After the return, I'm manually creating the pagination.

I'll just leave the code as well here:

protected function paginate(Collection $offerings): LengthAwarePaginator
{
    $page = request()->page ?? 1;

    $perPage = $this->config->take;

    $offset = ($page * $perPage) - $perPage;

    return new LengthAwarePaginator(
        array_slice($offerings->all(), $offset, $perPage, true),
        $offerings->count(), 
        $perPage, 
        $page,
        [
            'path' => request()->url(),
            'query' => request()->query()
        ]
    );
}

This current approach is much faster than using paginate.

But my problem is it is still loading 300 rows.

My goal is to load only 18 rows per page. And calculate the correct total until it hits 300. It won't go above.

The numbers are taken from Airbnb, so I can show you this picture, so you maybe know what I'm after at:

Airbnb is always limiting it's max total to 300. Because 18 rows are loaded, we get 17 pages.

Any idea how to solve this?

Upvotes: 0

Views: 2434

Answers (1)

Philipp Mochine
Philipp Mochine

Reputation: 4705

Just for you, readers in the future. I'm lucky in that sense that I could limit my sub join ->limit(300)

With that I could now use paginate. Now it is not slow anymore at all!

I tested it against manual pagination like with:

return $offersQuery->offset($this->offset)
                           ->limit($this->perPage)
                           ->get();

and it does not matter what you are going to use.

Upvotes: 1

Related Questions