zoldic's avatar

How to use LengthAwarePaginator (Manual Paginator) with appends & sortby/orderby

Hi folks, I have no idea how to use the LengthAwarePaginator (Laravel Doc didn't explain how to use this class)

use Illuminate\Pagination\LengthAwarePaginator;

$solved = array();
foreach(Thread::all() as $thread)
{
    if($thread->hasCorrectAnswer())
    {
        array_push($solved, $thread);
    }
}

$results = new LengthAwarePaginator($solved, 11);

This is how to use the regular automatic paginator method

$results = Thread::where('user_id', Auth::id())->orderBy('created_at', 'desc')->paginate(15)->appends('filter', request('filter'));

My question is: how to use the LengthAwarePaginator and how to add the "orderBy" and "appends" to that manual paginator?

0 likes
14 replies
Snapey's avatar

what are request->filter ?

my understanding is that appends is used on the links not the paginator?

$threads= Auth::user()->threads()->latest()->paginate(15);

later, in view


{{ $threads->appends($filter)->links(); }}

i haven't tried adding appends in the controller, but I suppose it should work

zoldic's avatar

It is for filter thread, just like laracast, filter: my question, my participation, my favorites, etc

in my case, for my filter solved it would be like this

web.dev/?filter=solved
web.dev/?filter=solved&page=1  //next page filter
web.dev/?filter=solved&page=2

this code work just fine

$results = Thread::where('user_id', Auth::id())->orderBy('created_at', 'desc')->paginate(15)->appends('filter', request('filter'));

but I have no idea how to use the LengthAwarePaginator and how to add "appends" and "orderBy"

zoldic's avatar

Thanks for the help

I have fixed my code, but I still have problem, I can't orderby/sortby my thread based on created_at

->orderBy('created_at', 'desc')

$items = array();
foreach(Thread::all() as $thread)
{
    if($thread->hasCorrectAnswer())
    {
        array_push($items, $thread);
    }
}

$currentPage = LengthAwarePaginator::resolveCurrentPage();
$perPage = 11;
$currentItems = array_slice($items, $perPage * ($currentPage - 1), $perPage);

$paginator = new LengthAwarePaginator($currentItems, count($items), $perPage, $currentPage);
$results = $paginator->appends('filter', request('filter'));
Snapey's avatar

I don't really understand why you are getting all threads and then filtering it down in a loop. Why not set the query correctly in the first place?

You will then be able to apply the paginator to the eloquent collection

Your hasCorrectAnswer() could be setup as a model scope

What does hasCorrectAnswer do?

zoldic's avatar

The reason is because I can't really query my Thread model directly, I loop all my thread is to check whether a single thread has a reply that has been mark as correct answer (a thread with a correct answer)

the hasCorrectAnswer() method in my Thread.php model

public function hasCorrectAnswer() {
    return $this->replies->where('correct_answer', 1)
->first()['correct_answer'];
}

I want to query it in the first place, but I believe it is not possible (CMIIW)

BTW the LengthAwarePaginator already worked, I just have problem with ordering/sorting it based on the created_at date

zoldic's avatar
zoldic
OP
Best Answer
Level 1

Thanks to everyone that has been helping out

I managed to solve it now

$items = array();
foreach(Thread::all() as $thread)
{
    if($thread->hasCorrectAnswer())
    {
        array_push($items, $thread);
    }
}

$currentPage = LengthAwarePaginator::resolveCurrentPage();
$perPage = 11;

$items = array_reverse(array_sort($items , function ($value) {
    return $value['created_at'];
}));
$currentItems = array_slice($items, $perPage * ($currentPage - 1), $perPage);

$paginator = new LengthAwarePaginator($currentItems, count($items), $perPage, $currentPage);
$results = $paginator->appends('filter', request('filter'));
break;

Another guide from jlrdw https://laracasts.com/discuss/channels/guides/length-aware-paginator

4 likes
Snapey's avatar

out of interest, have you checked how many database queries you are running... this is going to be horrible, and get worse as content increases.

zoldic's avatar

Queries? I think this is the line of code that has queries in it

foreach(Thread::all() as $thread)
{
    if($thread->hasCorrectAnswer())
    {
        array_push($items, $thread);
    }
}

where hasCorrectAnswer is

public function hasCorrectAnswer() {
    return $this->replies->where('correct_answer', 1)
->first()['correct_answer'];
}
Snapey's avatar

queries...

well you seem to have classic n+1 issue

if you have 50 threads then you will execute one query to get the threads and then 50 queries to get the replies for each thread

=51 queries

if there are 500 threads then you will do 501 queries

kapitan's avatar

used this fix. thank you so much for this!

Please or to participate in this conversation.