如何使用 Laravel API 资源对加载的关系进行分页

Posted

技术标签:

【中文标题】如何使用 Laravel API 资源对加载的关系进行分页【英文标题】:How to Paginate loaded relation with Laravel API resources 【发布时间】:2019-11-30 18:00:59 【问题描述】:

我需要在它的资源中加载模型关系并对其进行分页。

就我而言,我有 CategoryPath 模型,以及 CategoryResourcePathResource

CategoryResourcetoArray 方法如下:

public function toArray($request)

    return [
        'id'   => $this->id,
        'name' => $this->name,
        'slug' => $this->slug,
        'order' => $this->order,
        'paths' => PathResource::collection($this->whenLoaded('paths'))
    ];

PathResourcetoArray 方法如下:

public function toArray($request)

    return parent::toArray($request);

问题是如何在我的CategoryResource 中加载和分页相关的Path

【问题讨论】:

您找到解决问题的方法了吗?我也对同样的问题感到震惊,找不到答案 @LizeshShakya 我发布了这个问题的答案。 【参考方案1】:

我遇到了同样的问题并通过这种方式解决了:

先决条件

您必须拥有/创建Path 模型的资源,即PathResource 创建一个使用这个命令:

php artisan make:resource PathResource

解决方案

解决方案是在关系上使用 laravel paginate 并在分页集合上使用 transform 方法将其项目转换为您的资源。

第一步

使用以下命令创建一个基类,用于对应用中的任何资源进行分页:

php artisan make:resource PaginatedCollection -c

编辑PaginatedCollection并添加以下代码:

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class PaginatedCollection extends ResourceCollection


    /**
     * An array to store pagination data that comes from paginate() method.
     * @var array
     */
    protected $pagination;

    /**
     * PaginatedCollection constructor.
     *
     * @param mixed $resource paginated resource using paginate method on models or relations.
     */
    public function __construct($resource)
    

        $this->pagination = [
            'total' => $resource->total(), // all models count
            'count' => $resource->count(), // paginated result count
            'per_page' => $resource->perPage(),
            'current_page' => $resource->currentPage(),
            'total_pages' => $resource->lastPage()
        ];

        $resource = $resource->getCollection();

        parent::__construct($resource);
    

    /**
     * Transform the resource collection into an array.
     * now we have data and pagination info.
     *
     * @param \Illuminate\Http\Request $request
     * @return array
     */
    public function toArray($request)
    
        return [
            // our resources
            'data' => $this->collection,

            // pagination data
            'pagination' => $this->pagination
        ];
    

第二步

为您的模型创建一个集合资源并扩展PaginatedCollection 而不是默认的ResourceCollection

运行以下命令:php artisan make:resource PathCollection -c

现在编辑您的新集合类 PathCollection 并覆盖 toArray 方法:

/**
 * Transform the resource collection into an array.
 *
 * In this method use your already created resources
 * to avoid code duplications
 *
 * @param \Illuminate\Http\Request $request
 * @return array
 */
public function toArray($request)

    return [

        // Here we transform any item in paginated items to a resource

        'data' => $this->collection->transform(function ($path) 
            return new PathResource($path);
        ),

        'pagination' => $this->pagination,
    ];

最后一步

在您的CategoryResource 中使用PathCollection,如下所示:

return [
    'id'   => $this->id,
    'name' => $this->name,
    'slug' => $this->slug,
    'order' => $this->order,
    'paths' => new PathCollection(
        new LengthAwarePaginator(
            $this->whenLoaded('paths'),
            $this->paths_count,
            10
        )
    ),
];

并确保导入 LengthAwarePaginator 类:use Illuminate\Pagination\LengthAwarePaginator;

用法

$category = Category::with('paths')->withCount('paths')->find(1);
return new CategoryResource($category);

【讨论】:

【参考方案2】:

您可能应该查看有关 Resources 和 ResourceCollections 的文档。 ResourceCollections 将允许您轻松地对资源进行分页。 Api Resource Collection Pagination Documentation

【讨论】:

该文档仅显示了如何对整个模型进行分页。问题是如何在 toArray 方法中对资源内部模型的关系进行分页?

以上是关于如何使用 Laravel API 资源对加载的关系进行分页的主要内容,如果未能解决你的问题,请参考以下文章

Laravel - 与资源的关系和加载时不起作用

在laravel api中对关系资源进行分页

Laravel 5.6 API 资源未显示关系数据

Laravel 5.4 - 如何对急切加载关系进行分页

Laravel API JSON 自定义和表关系

向 eloquent 资源添加过滤器以有条件地附加关系