自定义 Laravel 5.5 Api 资源集合分页

Customising Laravel 5.5 Api Resource Collection pagination

我一直在使用 laravel api 资源。默认情况下 laravel 提供链接和元数据,如下所示。

"links": {
    "first": "https://demo.test/api/v2/taxes?page=1",
    "last": "https://demo.test/api/v2/taxes?page=4",
    "prev": null,
    "next": "https://demo.test/api/v2/taxes?page=2"
},
"meta": {
   "current_page": 1,
   "from": 1,
   "last_page": 4,
   "path": "https://demo.test/api/v2/taxes",
   "per_page": 2,
   "to": 2,
   "total": 8
} 

但我不想要这个,我想要类似的东西

"pagination": {
  "total": 8,
  "count": 8,
  "per_page": 25,
  "current_page": 1,
  "total_pages": 1
}

我能够获取此信息,但如果我这样做 return TaxResource::collection($taxes);,我将无法获取此信息。即使我有自定义收集方法

 public static function collection($resource)
    {
       $resource->pagination = [
        'total' => $resource->total(),
        'count' => $resource->count(),
        'per_page' => $resource->perPage(),
        'current_page' => $resource->currentPage(),
        'total_pages' => $resource->lastPage()
       ];
        return parent::collection($resource);
    }

这不是我想要的。但是,如果我通过 (TaxResource::collection($taxes))->pagination; 进行引用,我就能得到它。但是我希望它在我 return TaxResource::collection($taxes);

时被归还

我对你的问题很感兴趣,并花了一些时间来解决它。我想还有很多工作要做,以改进 Eloquent: API Resources' 未来的功能。

为了解决它,我必须使用 Resource Collections 而不是 Resources:

However, if you need to customize the meta data returned with the collection, it will be necessary to define a resource collection

php artisan make:resource Tax --collection

php artisan make:resource TaxCollection

路线:

Route::get('/get-taxes', function () {
    $taxes = Taxes::paginate();
    return new TaxCollection($taxes);
});

TaxCollection.php:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class TaxCollection extends ResourceCollection
{        
    public function toArray($request)
    {
        return [
        'data' => $this->collection,
        'pagination' => [
            'total' => $this->total(),
            'count' => $this->count(),
            'per_page' => $this->perPage(),
            'current_page' => $this->currentPage(),
            'total_pages' => $this->lastPage()
        ],
    ];
    }  

    // Using Laravel < 5.6
    public function withResponse($request, $response)
    {
        $originalContent = $response->getOriginalContent();
        unset($originalContent['links'],$originalContent['meta']);
        $response->setData($originalContent);
    }

    // Using Laravel >= 5.6
    public function withResponse($request, $response)
    {
        $jsonResponse = json_decode($response->getContent(), true);
        unset($jsonResponse['links'],$jsonResponse['meta']);
        $response->setContent(json_encode($jsonResponse));
    }
}

这解决了问题,但现在有新问题: 与 Resources 不同,我不知道如何修改 Resource Collections 中的 toArray 字段,手册只显示 [=15= 的示例] 我们发送未修改的集合(资源集合 允许我们更改元数据)。所以如果我们只使用 Resource 那么我们可以修改集合数据而不是元数据。

您还可以扩展 JsonResource、AnonymousResourceCollection、ResourceCollection,最后扩展 PaginatedResourceResponse

接受的答案对我不起作用(在 Laravel 5.6 中),但恕我直言,我找到了更好的方法。

将分页信息保存在您的 ResourceCollection 构造函数中,并将 Paginator 资源替换为基础 Collection。

TaxCollection.php:

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class TaxCollection extends ResourceCollection
{
    private $pagination;

    public function __construct($resource)
    {
        $this->pagination = [
            'total' => $resource->total(),
            'count' => $resource->count(),
            'per_page' => $resource->perPage(),
            'current_page' => $resource->currentPage(),
            'total_pages' => $resource->lastPage()
        ];

        $resource = $resource->getCollection();

        parent::__construct($resource);
    }

    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'pagination' => $this->pagination
        ];
    }
}

@yrv16 Laravel 5.6 版本:

public function withResponse($request, $response)
{
    $jsonResponse = json_decode($response->getContent(), true);
    unset($jsonResponse['links'],$jsonResponse['meta']);
    $response->setContent(json_encode($jsonResponse));
}

所以我发现在 PHP 中您实际上可以调用祖父函数而无需反射或其他变通方法。

鉴于 TaxCollection 扩展了 ResoureCollection,后者又扩展了 JsonResource,我们实际上可以绕过处理分页的 ResourceCollection 方法。

class TaxCollection extends ResourceCollection
{        
    public function toArray($request)
    {
        return [
        'data' => $this->collection,
        'pagination' => [
            'total' => $this->total(),
            'count' => $this->count(),
            'per_page' => $this->perPage(),
            'current_page' => $this->currentPage(),
            'total_pages' => $this->lastPage()
        ],
    ];
    }  

    public function toResponse($request)
    {
        return JsonResource::toResponse($request);
    }
}

toResponse 方法调用不是静态的,而是调用祖父 JsonResource::toResponse 方法,就像 parent::toResponse 调用 ResourceCollection toResponse(..) 实例方法一样。

这将从 JSON 响应(链接、元等)中删除所有额外的分页字段,并允许您根据需要在 toArray($request)

中自定义响应

JsonResource class 附带一个 additional() 方法,它允许您指定在使用资源时希望成为响应一部分的任何其他数据:

   Route::get('/get-taxes', function () {
    $taxes = Taxes::paginate();
    return new TaxCollection($s)->additional([
       'pagination' => [
          'total' => $taxes->total,
           ...
        ]
      ]);
   });