1

I am trying to list entries in a table by Month, Year:

  • May, 2015
    • Item 1
    • Item 2
    • Item 3
  • June, 2015
    • Item 1
    • etc..

I have achieved this with the following code but I would also like to paginate the results. I have tried many different things but none of them seem to work, I am using Laravel 5.

$events = App\Events->orderBy('start', 'asc')->get()->groupBy(function($date) {
            return $date->start->format('F, Y');
        });

Here is the output for the above query:

{
    "April, 2015": [
        {
            "id": "10",
            "event_type_id": "1",
            "user_id": "1",
            "title": "Testing",
            "slug": "testing",
            "start": "2015-04-23 17:00:00",
            "end": "2015-04-23 17:40:00",
            "description": "<h1>MEETING!</h1><p>Let's try this in HTML!<br></p>",
            "created_at": "2015-04-19 14:18:33",
            "updated_at": "2015-04-21 22:07:41",
            "type": {
                "id": "1",
                "name": "General",
                "slug": "general",
                "created_at": "2015-04-18 11:24:00",
                "updated_at": "2015-04-18 11:24:04"
            }
        }
    ],
    "May, 2015": [
        {
            "id": "12",
            "event_type_id": "1",
            "user_id": "1",
            "title": "Test Event",
            "slug": "test-event",
            "start": "2015-05-15 18:00:00",
            "end": null,
            "description": "<p>This is a test event with just a start time</p>",
            "created_at": "2015-04-21 14:59:56",
            "updated_at": "2015-05-02 18:37:53",
            "type": {
                "id": "1",
                "name": "General",
                "slug": "general",
                "created_at": "2015-04-18 11:24:00",
                "updated_at": "2015-04-18 11:24:04"
            }
        },
        {
            "id": "9",
            "event_type_id": "1",
            "user_id": "1",
            "title": "Monthly Meeting",
            "slug": "monthly-meeting",
            "start": "2015-05-23 14:00:00",
            "end": "2015-04-16 20:00:00",
            "description": "<p>It's a long monthly meeting!</p>",
            "created_at": "2015-04-19 13:13:45",
            "updated_at": "2015-05-03 08:45:56",
            "type": {
                "id": "1",
                "name": "General",
                "slug": "general",
                "created_at": "2015-04-18 11:24:00",
                "updated_at": "2015-04-18 11:24:04"
            }
        }
    ],
    "June, 2015": [
        {
            "id": "11",
            "event_type_id": "1",
            "user_id": "1",
            "title": "Another Meeting Saved",
            "slug": "another-meeting-saved",
            "start": "2015-06-19 18:00:00",
            "end": null,
            "description": "<p>It's another meeting afterall</p>",
            "created_at": "2015-04-20 15:03:30",
            "updated_at": "2015-05-03 08:46:19",
            "type": {
                "id": "1",
                "name": "General",
                "slug": "general",
                "created_at": "2015-04-18 11:24:00",
                "updated_at": "2015-04-18 11:24:04"
            }
        }
    ]
}

With LengthAwarePaginator -

$paginator = new LengthAwarePaginator($events, count($events), 1);
    return $paginator;

This returns the paginator but the data is the same - meaning the same result set as without the paginator, when I'd expect only one record to be returned per page:

    [{
    "total": 3,
    "per_page": 1,
    "current_page": 1,
    "last_page": 3,
    "next_page_url": "/?page=2",
    "prev_page_url": null,
    "from": 1,
    "to": 3,
    "data": {
        "data" : ".. same as above"
    }
}]
NightMICU
  • 9,000
  • 30
  • 89
  • 121
  • Did you try `->paginate()`? – toesslab May 02 '15 at 17:32
  • Yes, I think if I replace `->get()` with `->paginate()` it limits the result set to whatever number I provide but it does not include the rest of the paginate functionality - like pages – NightMICU May 02 '15 at 17:35
  • Is the request POST or GET? – toesslab May 02 '15 at 17:37
  • GET, I will be displaying results on an HTML page – NightMICU May 02 '15 at 17:49
  • Can you post you view, pls – toesslab May 02 '15 at 17:50
  • Sorry, but it really isn't relevant here. Something about the query makes it not return all of the pagination features - so `$events->render()` throws an error (because of the missing pagination properties). I am looking at the result of `dd($events)`, no view needed. – NightMICU May 02 '15 at 18:02
  • Sry, just trying to find the error, often, the error is in the view itself... but it seems another problem, which I can't find out without seeing more of your code. The "normal" query is working though? – toesslab May 02 '15 at 18:06
  • Sorry.. the only code that matters here is the Eloquent query. There are no error messages, the code provided outputs the results as desired but *not* paginated - that's what I am trying to figure out. – NightMICU May 02 '15 at 18:08
  • Sry I couldn't help man! – toesslab May 02 '15 at 18:09
  • As stated in the Laravel docs...Note: Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually. [Docs](http://laravel.com/docs/5.0/pagination#usage) – aethergy May 02 '15 at 19:35
  • @aethergy Ahhh missed that. I'll have to look up manual paginator creation.. could not find information in the docs regarding that. Feel free to post your comment as an answer and I'll accept it. – NightMICU May 02 '15 at 22:24
  • @aethergy I'm finding this kind of clunky and not really seeming to work. If I use `$paginator = new Paginator($events, count($events), 1, 1);` it is acting the same way as before, I see no pagination going on (using LengthAwarePaginator). Do I have to do something else to actually make this work? Finding a lot of old forum posts related to this but they do not seem to work or apply to what I'm after. – NightMICU May 02 '15 at 22:49
  • What do you get from 'dd($paginator)'? – aethergy May 03 '15 at 03:53
  • You can follow this: https://stackoverflow.com/a/59174052/6189461 – Rafik Farhad Dec 04 '19 at 10:42

4 Answers4

3

With aggregates you need to implement your own custom paginator, as stated by docs:

Note: Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually.

See this posts to manually implement pagination:

Laravel 5 - Manual pagination

Manually Creating a Paginator (Laravel 5)

Community
  • 1
  • 1
Edgar Orozco
  • 2,722
  • 29
  • 33
  • Please see updated question. The documentation isn't really helpful apart from saying you can't do something and then saying "use this class." The posts you link to basically reiterate this, one answer says "I *guess* it's something like this." Not terribly helpful. Anyway, I seem to have successfully created a paginator object but I'm still getting the same number of results (not paginated). – NightMICU May 03 '15 at 12:55
  • Okay, it seems like the part that I'm missing here is the fact that I need to use `->take()` and `->limit()` in my query - based on the current page and number per page. I have seen zero mention of this related to manual pagination.. I figured that this was somehow taken care of for me.. or can it be somehow? – NightMICU May 03 '15 at 13:38
2

Many people have pointed me to a widely mentioned paragraph in the Laravel documentation,

Note: Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually.

Not terribly helpful, since I cannot find any example in the documentation as to exactly how to create a manual paginator using the results of an Eloquent query. So, here is what I was able to come up with. Note that you must use ->take() and ->offset() in the query, otherwise you will end up with the same results on every page (this is where I was getting stuck).

<?php
// routes.php
use Illuminate\Pagination\LengthAwarePaginator as Paginator;
    get('test', function(Request $request) {
        $page = $request->has('page') ? $request->input('page') : 1; // Use ?page=x if given, otherwise start at 1
        $numPerPage = 2; // Number of results per page
        $eventType = EventType::find(1); // Not relevant to pagination
        $count = $eventType->memberEvents()->count(); // Get the total number of entries you'll be paging through
        // Get the actual items
        $events = $eventType->memberEvents()->orderBy('start', 'asc')
            ->take($numPerPage)->offset(($page-1)*$numPerPage)->get()->groupBy(function($date) {
            return $date->start->format('F, 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($events, $count, $numPerPage, $page, ['path' => $request->url(), 'query' => $request->query()]);
        return $paginator;
    });
NightMICU
  • 9,000
  • 30
  • 89
  • 121
1

If you want to add groupBy to your data the you should use LengthAwarePaginator object as updated in laravel 5

Try this,

use Illuminate\Pagination\LengthAwarePaginator as Paginator;

$page       = ($request->input('page') != null) ? $request->input('page') : 1;
$perPage    = 1;

$sliced     = array_slice($data, 0, 5); //you can these values as per your requirement 

$paginator  = new Paginator($sliced, count($data), $perPage, $page,['path'  => url()->current(),'query' => $request->query()]);

return $paginator;

$data is your data object and fifth parameters are for next and prev urls

Refer this for more information about paginator, https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Builder.html#method_paginate

AmarjaPatil4
  • 1,640
  • 3
  • 28
  • 41
0

As stated in the Laravel docs...Note: Currently, pagination operations that use a groupBy statement cannot be executed efficiently by Laravel. If you need to use a groupBy with a paginated result set, it is recommended that you query the database and create a paginator manually. Docs

aethergy
  • 723
  • 2
  • 7
  • 16