boneill81's avatar

Retrieve all items using pagination

Hi Guys, I have a useful and clean search method which builds up an eloquent query based on attributes that are sent to it. At the minute it uses get() and works fine. I now want to add in pagination which again works. However at the minute I am doing the following:

if (!empty($parameters['page'])) {
    $results = $query->with('customAttributes')->orderBy('created_at', 'desc')->paginate();
}else{
    $results = $query->with('customAttributes')->orderBy('created_at', 'desc')->get();
}

I was wondering if there is not perhaps a nicer built in way to do this. For example pass false to paginate in which case it returns all records as per a normal get() which it executes internally anyway.

Thanks

0 likes
8 replies
thinkbasis's avatar

@s4muel as mentioned, 0 or false doesn't work because "paginate" method checks if a passed parameter is false (!!0 is false too) and takes a default model value for pagination which is 15. So another way is changing a default model "perPage" value (in a parent "Model" class or in a specific model you need it work to) to some large amount (say, 10000, as Snapey suggested). After that, the construction "paginate(0)" will take that large amount.

It's a really late reply, but I faced the same question and get to this page when was Googling. So I decided to share my experience that may be helpful for someone.

1 like
Snapey's avatar
Snapey
Best Answer
Level 122

It would probably simplify your view also if you assumed that it was always paginated but that the pagination was a large number?

$results = $query->with('customAttributes')
                       ->orderBy('created_at', 'desc')
                       ->paginate($parameters['page'] ?10:10000);

I don't think links() outputs anything if there is only one page

2 likes
boneill81's avatar

@S4MUEL - Sadly I spoke too soon. Neither zero, false or anything else I tried works. I am perhaps just going to have to stick with my initial solution it seems.

1 like
boneill81's avatar

@SNAPEY - I relooked at this and in effect this is the answer. Thanks for your help it was very useful. You would rarely if ever really be retrieving such a large amount in a single web request and hence this does exactly what I want. Thanks again.

keizah7's avatar
Manufacturer::query()
    ->withCount('models')
    ->when($request->per_page, fn (Builder $query, $perPage) => $query->paginate($perPage))
    ->when($request->show_all, fn (Builder $query) => $query->get())
4 likes
mikegh's avatar
        $results = $query
            ->when(isset($validatedRequest['per_page']),
                fn($query) => $query->paginate($validatedRequest['per_page']),
                fn($query) => $query->get());

You may pass another closure as the third argument to the when method. This closure will only execute if the first argument evaluates as false. source: https://laravel.com/docs/10.x/queries#conditional-clauses

1 like
C-ArenA's avatar

I know this is an old thread, but I've found a solution I think can be useful. Reading the api documentation of Laravel I've found that the paginate() method can receive a closure as the first parameter. This closure receives the $total count of the results so you could use it this way:

$results = $query->paginate(function($total) use ($request){
	$perPage = $request->get('per_page', 15);
	if($perPage == 'all'){
		return $total;
	}
	return $perPage;
}
)

This is my first reply here at Laracasts, be kind :)

1 like

Please or to participate in this conversation.