Search code examples
phplaravelpaginationlaravel-5eager-loading

Laravel pagination using double eager loading


I'm using the following code in my ForumController:

public function boardIndex($id)
{
    $container = ForumBoard::with([
        'topics' => function($query)
            {
                $query->orderBy('created_at', 'desc');
                $query->paginate(10);
            },
        'children' => function($query)
            {
                $query->orderBy('position', 'asc');
            }
        ])->findOrFail($id);

    return view('forum.board.index', compact('container'));
}

It works as expected, I can manually paginate by appending ?page=2 to the end of the url, however if I want to render the paginator in my view using {!! $container->topics->render() !!} I get the following error:

ErrorException in Macroable.php line 81:
Method render does not exist. (View: C:\xampp\htdocs\see\resources\views\forum\board\index.blade.php)

EDIT:

Thanks for the help! Here's my final, working code (it's even using only 4 database queries instead of 5):

public function boardIndex($id)
{
    $board = ForumBoard::findOrFail($id);
    $topics = $board->topics()->latest()->paginate(11);
    $children = $board->children()->oldest('position')->get();

    return view('forum.board.index', compact('board', 'topics', 'children'));
}

Solution

  • I could not find the Paginator instance anywhere.

    Apparently when you paginate inside the closure, only the paginated results are stored.

    I came up with a solution that in my opinion is not elegant but may prove helpful:

    <?php
    public function index()
    {
        $descendantPaginator = null;
        $user = User::with([
            'descendants' => function ($query) use (&$descendantPaginator) {
                $query->orderBy('created_at', 'DESC');
                $descendantPaginator = $query->paginate(10);
            }
        ])->findOrFail(1);
    
        return view('home.index', compact('user', 'descendantPaginator'));
    }
    

    In your view:

    {!! $descendantPaginator->links() !!}
    

    I recommend the following strategy instead:

    <?php
    public function index()
    {
        $user = User::findOrFail(1);
        $descendants = $user->descendants()->latest()->paginate(10);
        return view('home.index', compact('user', 'descendants'));
    }
    

    Then in your view:

    {!! $descendants->links() !!}