如何对 Laravel 集合进行分页?

5

以下是我尝试分页的方法:

$posts = Post::all()->sortByDesc("created_at")->pagination(1);

但我遇到了这个错误:

方法 Illuminate\Database\Eloquent\Collection::pagination 不存在。


1
如果您只需要返回最新的一条记录,那么只需使用Post::latest()->paginate(1)即可,无需将所有记录加载到集合中再返回其中的一条。 - lagbox
1
这个回答解决了你的问题吗?如何在Laravel 5中对合并的集合进行分页? - miken32
6个回答

25

创建一个辅助类

<?php

namespace App\Helpers;

use Illuminate\Container\Container;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;

class PaginationHelper
{
    public static function paginate(Collection $results, $showPerPage)
    {
        $pageNumber = Paginator::resolveCurrentPage('page');
        
        $totalPageNumber = $results->count();

        return self::paginator($results->forPage($pageNumber, $showPerPage), $totalPageNumber, $showPerPage, $pageNumber, [
            'path' => Paginator::resolveCurrentPath(),
            'pageName' => 'page',
        ]);

    }

    /**
     * Create a new length-aware paginator instance.
     *
     * @param  \Illuminate\Support\Collection  $items
     * @param  int  $total
     * @param  int  $perPage
     * @param  int  $currentPage
     * @param  array  $options
     * @return \Illuminate\Pagination\LengthAwarePaginator
     */
    protected static function paginator($items, $total, $perPage, $currentPage, $options)
    {
        return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
            'items', 'total', 'perPage', 'currentPage', 'options'
        ));
    }
}

当您想要添加帮助程序文件时,请打开composer.json文件。Composer具有一个名为“files”的键(文件路径数组),您可以在autoload内定义它。

"autoload": {
    "files": [
        "app/Helpers/PaginationHelper.php"
    ],
    "classmap": [
        "database/seeds",
        "database/factories"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},

现在您需要在终端中键入此命令

composer dump-autoload

现在您可以创建一个分页集合,就像下面的示例一样

Route::get('/test_collect_pagintae', function () {

    $users = \App\User::get();

    $showPerPage = 20;

    $paginated = PaginationHelper::paginate($users, $showPerPage);

    return $paginated;
});

这是我见过的最清晰的LengthAware助手实现示例。我想问一下$options是什么,我该如何使用它? - Shulz
@Shulz 表示(路径,查询,片段,页面名称)来源 - undefined

6

您可以在app/provider/serviceProvider文件的boot方法中使用此代码。

Collection::macro('paginate', function($perPage, $page = null, $pageName = 'page') {
            $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);
            return new LengthAwarePaginator(
                $this->forPage($page, $perPage), // $items
                $this->count(),                  // $total
                $perPage,
                $page,
                [                                // $options
                    'path' => LengthAwarePaginator::resolveCurrentPath(),
                    'pageName' => $pageName,
                ]
            );
        });

嗨,你好,我正在尝试使用 Laravel 9 和 PHP 8.1.3,但是 forPage 和 count 方法似乎无法识别。 - Arek TG
我尝试过使用 Laravel 9 和 PHP 8.1.7,它工作正常。 - Lenor

6

1

解决方案

这是来自simonhamp的非常好的解决方案,感谢他。simonhamp

我的建议是在AppServiceProvider中执行->values(),如下所示。这很重要,因为在切片集合时,键被保留,我们不希望分页器保留键。

Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
    $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

    return new LengthAwarePaginator(
        $total ? $this : $this->forPage($page, $perPage)->values(),
        $total ?: $this->count(),
        $perPage,
        $page,
        [
            'path' => LengthAwarePaginator::resolveCurrentPath(),
            'pageName' => $pageName,
        ]
    );
});

0

您可以轻松地进行分页,只需删除所有“-”即可:

$posts = Post::sortByDesc("created_at")->pagination(1);

在我的情况下,我必须合并多个集合,然后对合并的数据进行分页,所以我必须像这样做:
$items = $items2->merge($items1);
$items = $this->paginate($items);

public function paginate($items, $perPage = 15, $page = null, $options = [])
{
    $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
    $items = $items instanceof Collection ? $items : Collection::make($items);
    return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}

参考:Laravel文档, 如何对Laravel集合进行分页?


-1

尝试这段代码:


//convert to array
$posts = Post::all()->sortByDesc("created_at")->toArray();

//Create new pagination
$currentPage = LengthAwarePaginator::resolveCurrentPage();
$perPage = 3;
$currentItems = array_slice($posts, $perPage * ($currentPage - 1), $perPage);
//with path of current page
$posts = (new LengthAwarePaginator($currentItems, count($posts ), $perPage, $currentPage))->setPath(route('posts....'));

//Convert array of array to array of object
$posts->each(function ($item, $itemKey) use($posts) {
     $posts[$itemKey] = (Object)$item;
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接