【问题标题】:Customising Laravel 5.5 Api Resource Collection pagination自定义 Laravel 5.5 Api 资源集合分页
【发布时间】:2018-06-14 03:39:47
【问题描述】:

我一直在使用 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; 进行引用,我就能得到它。但我希望它在我做@​​987654327@时被退回

【问题讨论】:

标签: laravel-5.5


【解决方案1】:

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

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

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

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 字段,该手册仅显示了 'data' =&gt; $this-&gt;collection 的示例,其中我们发送未修改的集合(资源集合允许我们更改元数据)。所以如果我们只使用 Resource 那么我们可以修改集合数据而不是元数据。

【讨论】:

  • 非常感谢,您的想法行之有效。好吧,我也有解决该问题的方法。而不是 ` 'data' => $this->collection` ,像这样使用变换 'data'=&gt; $this-&gt;collection-&gt;transform(function ($data) {return[ 'id' =&gt; $data-&gt;id,..] }) 。这将解决问题,但问题在于单个模型会出错。无论如何,非常感谢。
  • 设置时忘记json_encode $originalContent
  • 感谢您的问题/回答,我有时会在理解它并让它按预期工作后重新包装它:ask.osify.com/qa/11425
【解决方案2】:

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

【讨论】:

  • 这很好用,但是如果你想自定义返回的数据(过滤掉一些东西)怎么办。此外,您将无法为单行使用相同的资源。
  • 只需将'data' =&gt; $this-&gt;collection 替换为'data' =&gt; TaxResource::collection($this-&gt;collection)。这样您就可以自定义 TaxResource 类中的每个项目。
  • 请将$this-&gt;total()改为$resource-&gt;total()
  • 使用 laralve 5.6.25,在 toArray 中丢失了$this-&gt;collection,因此在构造函数中只需将选定的项目存储在自定义变量$this-&gt;items =$resource = $resource-&gt;getCollection(); 中,在toArray 中使用$this-&gt;items 而不是$this-&gt;collection跨度>
  • 这种方法最适合我。感谢分享!
【解决方案3】:

所以我发现在 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) 中根据需要自定义响应

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 同意,然后从这些基础继承,以将更改应用于新扩展基础的所有其他扩展,而不必将全局更改放入每个基础。
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      JsonResource 类带有一个 Additional() 方法,可让您在使用资源时指定您希望作为响应的一部分的任何其他数据:

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

      【讨论】:

        猜你喜欢
        • 2019-04-25
        • 1970-01-01
        • 2018-07-03
        • 1970-01-01
        • 2018-03-05
        • 2021-10-15
        • 2021-11-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多