brentxscholl's avatar

Paginating grouped By notifications

I am trying to display all notifications on a page and group them by day (to show a time timeline), but I am unable to properly paginate the notifications.

Here is my code:

View:

               @foreach ($notifications as $day => $notifications)
                    <div class="row notification-day">
                        <div class="col col-sm-2">
                            <div class="notification-date">
                                <p>{{ $day }}</p>
                            </div>
                        </div>
                        <div class="col col-sm-10">
                            <div class="notification-date-list">
                                <ul>
                                    @foreach($notifications as $n)
                                        <li>
                                            @include ('notification.timeline.' . snake_case(class_basename($n->type)))
                                        </li>
                                    @endforeach
                                </ul>
                            </div>
                        </div>
                    </div>
                @endforeach 

                  //......
                 {{ Auth::user()->notifications()->paginate(10)->links() }}

My controller

        $notifications = Auth::user()->notifications()->paginate(10)->groupBy(function($q) {
            return Carbon::parse($q->created_at)->format('d M Y');
        });


        return view('notification.timeline', compact('notifications'));

but this of course does not work. It does work fine if i remove the pagination attemp. all the notifications show on the page and are group as desired.

How can I group notifications by day, so I can separate the notifications on the page by the day, and also properly paginate?

Thanks!

0 likes
5 replies
brentxscholl's avatar

Thanks for the help @jlrdw . I'm an noobie and this is still very confusing. How can I make this work with the above groupBy query and in the controller?

jlrdw's avatar

Pagination and group by aren't a good marriage. A group by has to transverse the whole table to achieve results each time.

I'd look at a temp table, then paginate that. Also see if a pivot will work, I don't really use pivot table.

If you do not have too many results maybe you can just skip pagination.

1 like
brentxscholl's avatar
brentxscholl
OP
Best Answer
Level 17

This worked for me

use Illuminate\Pagination\LengthAwarePaginator as Paginator;

public function show(Request $request)
{
        $page = $request->has('page') ? $request->input('page') : 1; // Use ?page=x if given, otherwise start at 1
        $numPerPage = 5; // Number of results per page
        $userNotifications = Auth::user()->notifications();
        $count = $userNotifications->count(); // Get the total number of entries you'll be paging through
        // Get the actual items
        $notifications = $userNotifications
            ->take($numPerPage)->offset(($page-1)*$numPerPage)->get()->groupBy(function($q) {
                return Carbon::parse($q->created_at)->format('d M Y');
            });
        // Create the paginator with Illuminate\Pagination\LengthAwarePaginator as Paginator
        // Pass in the variables supplied above, including the path for pagination links
        $paginator = new Paginator($notifications, $count, $numPerPage, $page, ['path' => $request->url(), 'query' => $request->query()]);


        return view('notification.timeline', compact('notifications', 'paginator'));
}

The view is the same, replace {{ Auth::user()->notifications()->paginate(10)->links() }} with {{ $paginator }}

jlrdw's avatar

Is the question answered correctly if so can you mark.

Please or to participate in this conversation.