gretschduojet's avatar

Eager Loading with Pagination

Hello,

I have a user profile and a user can have many products. I am currently eager loading the users products and I'm able to display the products on the users profile. However, I would like to be able to paginate the products if the user has more than 5 products. What would be the best way to do that? Thank you in advance for the help.

0 likes
11 replies
thepsion5's avatar

Your best bet is probably to create the paginator yourself with the full set of results. I think you could do something like this:

$currentPage = Input::get('page', 1);
$perPage = 25;
$currentPageProducts = $user->products->chunk($perPage)[$currentPage - 1];
$totalProducts = $user->products->count();
$paginatedUserProducts = new LengthAwarePaginator($currentPageProducts, $totalProducts, $perPage, $currentPage);
1 like
bobbybouwmann's avatar

You can still do pagination with that. This is one of my sample projects and it works! In your case you only need to provide the products that are associated with the current user ;)

MoviesController.php

public function paginate()
{
    return Movie::with(['actors', 'producer'])->paginate(5);
}

Movie.php

public function actors()
{
    return $this->belongsToMany('App\Actor');
}

public function producer()
{
    return $this->belongsTo('App\Producer');
}
gretschduojet's avatar

Thank you for your responses - I will have to give that a try. Just so you can see what I have:

UsersController:

$user = User::with('ProductRegistration', 'UserNotes')->whereEmail($email)->firstOrFail();

View: Currently if a user has 20 products it will just list it - I would like to be able to paginate so it only shows 5 at a time.

 @forelse($user->ProductRegistration as $product)
                <div class="row">
                    <div class="panel panel-default">
                        <div class="panel-heading">
                            <h4> {{ $product->products['name'] }} </h4>
                        </div>
             </div> 
        </div>
@empty
   <p>No Products</p>
@endforelse

Thank You again for your help.

opb's avatar

@blackbird I think your method will paginate the movies. The original question translated to your scenario would be "Get film X along with the first 5 actors".

JarekTkaczyk's avatar
Level 53

@gretschduojet If you want to paginate one of the relations then you can do either:

$user = User::with('UserNotes')->whereEmail($email)->firstOrFail();
$products = $user->productRegistration()->paginate();

// then pass both variables to the view
return View::make('some.view', compact('user', 'products');
// and loop through the products directly
@foreach ($products as $product)

or this - but this in fact only fetches portion of the related rows, and returns Collection, instead of Paginator, so it is not the way to go if you want to be able to render links using ->ProductRegistration->render().

$user = User::with(['UserNotes', 'ProductRegistration' => function ($q) {
   $q->paginate();
}])->whereEmail($email)->firstOrFail();
10 likes
gretschduojet's avatar

Thank you all for your help. I definitely appreciate it and don't know what I would do without everyone at Laracasts.

cyberomin's avatar

Hi @gretschduojete, I followed your code, thank you very much. How do I render the links on the page. $result->render() doesn't seem to work.

Thank you.

JarekTkaczyk's avatar

@cyberomin Take a look at my answer above - I edited it with appropriate comment concerning render - you don't eager load with pagination if you want to render the links.

cyberomin's avatar

Thanks @JarekTkaczyk that means I can never use render. If that's the case, it defeats the purpose of pagination. Is there a work around for this?

Please or to participate in this conversation.