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

问题描述 投票:4回答:5

我一直在使用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);时,我希望它能被退回

laravel-5.5
5个回答
9
投票

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

为了解决它,我必须使用资源集合而不是资源:

但是,如果需要自定义随集合返回的元数据,则需要定义资源集合

php artisan make:资源税 - 收集

要么

php artisan make:资源TaxCollection

路线:

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

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

这解决了问题,但现在有了新问题:与资源不同,我不知道如何修改资源集合中的toArray字段,手册仅显示'data' => $this->collection的示例,其中我们发送未修改的集合(资源集合允许我们更改元数据)。因此,如果我们只使用Resource,那么我们可以修改收集数据,但不能修改元数据。


6
投票

接受的答案对我不起作用(在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
        ];
    }
}

1
投票

你还可以扩展JsonResource,AnonymousResourceCollection,ResourceCollection和最后的PaginatedResourceResponse


1
投票

所以我发现在PHP中你实际上可以在没有反射或其他变通方法的情况下调用祖父项功能。

鉴于TaxCollection扩展了ResoureCollection,而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)中自定义响应


0
投票

@ 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));
}
© www.soinside.com 2019 - 2024. All rights reserved.