Eloquent - 按月、年和分页分组

Posted

技术标签:

【中文标题】Eloquent - 按月、年和分页分组【英文标题】:Eloquent - Group By Month, Year and Paginate 【发布时间】:2015-07-12 08:02:33 【问题描述】:

我正在尝试按月、年列出表格中的条目:

2015 年 5 月 项目 1 第 2 项 项目 3 2015 年 6 月 项目 1 等等..

我已经使用以下代码实现了这一点,但我还想对结果进行分页。我尝试了很多不同的方法,但似乎都没有,我使用的是 Laravel 5。

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

这是上述查询的输出:


    "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"
            
        
    ]

使用 LengthAwarePaginator -

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

这会返回分页器,但数据是相同的 - 意味着与没有分页器的结果集相同,当我希望每页只返回一条记录时:

    [
    "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"
    
]

【问题讨论】:

你试过-&gt;paginate()吗? 是的,我想如果我用-&gt;paginate() 替换-&gt;get(),它会将结果集限制为我提供的任何数字,但它不包括其余的分页功能——比如页面 请求是 POST 还是 GET? GET,我将在 HTML 页面上显示结果 你能不能发表你的看法,请 【参考方案1】:

如果您想将 groupBy 添加到您的数据中,您应该使用在 laravel 5 中更新的 LengthAwarePaginator 对象

试试这个,

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 是您的数据对象,第五个参数用于下一个和上一个网址

有关分页器的更多信息,请参阅此处, https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Builder.html#method_paginate

【讨论】:

【参考方案2】:

许多人向我指出了 Laravel 文档中被广泛提及的一段,

注意:目前,使用 groupBy 语句的分页操作 Laravel 无法有效执行。如果您需要使用 groupBy 带有分页结果集,建议查询 数据库并手动创建分页器。

不是很有帮助,因为我在文档中找不到任何示例来准确如何使用 Eloquent 查询的结果创建手动分页器。所以,这就是我能想到的。请注意,您必须在查询中使用-&gt;take()-&gt;offset(),否则您最终会在每个页面上得到相同的结果(这是我卡住的地方)。

<?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;
    );

【讨论】:

【参考方案3】:

如 Laravel 文档中所述...注意:目前,使用 groupBy 语句的分页操作无法由 Laravel 有效执行。如果您需要使用带有分页结果集的 groupBy,建议您查询数据库并手动创建分页器。 Docs

【讨论】:

【参考方案4】:

使用聚合,您需要实现自己的自定义分页器,如 docs 所述:

注意:目前,使用 groupBy 语句的分页操作 Laravel 无法有效执行。如果您需要使用 groupBy 带有分页结果集,建议查询 数据库并手动创建分页器。

看这个帖子手动实现分页:

Laravel 5 - Manual pagination

Manually Creating a Paginator (Laravel 5)

【讨论】:

请查看更新后的问题。除了说你不能做某事然后说“使用这个类”之外,文档并没有真正的帮助。您链接的帖子基本上重申了这一点,一个答案说“我是这样的。”不是很有帮助。无论如何,我似乎已经成功创建了一个分页器对象,但我仍然得到相同数量的结果(未分页)。 好的,我在这里缺少的部分似乎是我需要在查询中使用-&gt;take()-&gt;limit() - 基于当前页面和每页数。我已经看到零次提及与手动分页相关的内容。我认为这是以某种方式为我处理的。或者它可以以某种方式吗?

以上是关于Eloquent - 按月、年和分页分组的主要内容,如果未能解决你的问题,请参考以下文章

Laravel Eloquent - hasrsine 公式和分页

Laravel/Eloquent 分页和 groupBy 用于 postgres 物化视图模型

Laravel Eloquent,添加有限行的关系变为空

Laravel 按 Eloquent 关系分组

不能用 PostgreSQL 与 eloquent 分组

Eloquent Laravel 按相关模型排序分页查询