php 如何删除Laravel分页响应的 meta对象中的链接?

rvpgvaaj  于 2023-06-28  发布在  PHP
关注(0)|答案(5)|浏览(151)

Laravel默认分页给我的响应与默认格式的分页,但我想删除链接 meta对象在页面响应
我使用下面的代码获取页面数据:

public function index()
{
  return response()->json(
     new EntityCollection(Entity::paginate($pageSize))
  );
}

它返回资源集合中的响应,我在代码中调用了EntityCollection。但我想删除在回应 meta中的链接。
EntityCollection看起来像这样:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class EntityCollection extends ResourceCollection
 {

 /**
  * Transform the resource collection into an array.
  *
  * @param  \Illuminate\Http\Request  $request
  * @return array
  */
  public function toArray($request)
  {
     return [
        'data' => $this->collection,
     ];

  }
}

当我使用EntityCollection来获取列表时,它会返回下面的格式响应:

{
"data": [
    // data
],
"links": {
    "first": "*url?page_size=1&page=1",
    "last": "*url?page_size=1&page=15",
    "prev": null,
    "next": "*url?page_size=1&page=2"
},
"meta": {
    "current_page": 1,
    "from": 1,
    "last_page": 15,
    "links": [
        {
            "url": null,
            "label": "pagination.previous",
            "active": false
        },
        {
            "url": "*url?page_size=1&page=6",
            "label": 6,
            "active": false
        }
   ],
    "path": "*url",
    "per_page": "1",
    "to": 1,
    "total": 15
 }
}

请给予我的方式来删除 meta或最佳实践,以自定义分页在Laravel的响应。

sycxhyv7

sycxhyv71#

我的解决方案:

<?php

namespace App\Core\Resources;

use Illuminate\Http\Resources\Json\AnonymousResourceCollection;

class AppAnonymousResourceCollection extends AnonymousResourceCollection
{
    public function paginationInformation($request, $paginated, $default): array
    {
        return [
            'pagination' => [
                'currentPage' => $paginated['current_page'],
                'from' => $paginated['from'],
                'lastPage' => $paginated['last_page'],
                'perPage' => $paginated['per_page'],
                'to' => $paginated['to'],
                'total' => $paginated['total'],
            ]
        ];
    }
}
<?php

namespace App\Core\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class AppJsonResource extends JsonResource
{
    public static function collection($resource)
    {
        return tap(new AppAnonymousResourceCollection($resource, static::class), function ($collection) {
            if (property_exists(static::class, 'preserveKeys')) {
                $collection->preserveKeys = (new static([]))->preserveKeys === true;
            }
        });
    }
}
class AcmeResource extends AppJsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  Request| null  $request
     * @return array
     */
    public function toArray($request = null): array
    {
        return [
            ...
        ];
    }
}

在控制器上。

return AcmeResource::collection($collection->paginate($limit))
            ->response();

结果:

{
    "data": [
        ...
    ],
    "pagination": {
        "currentPage": 2,
        "from": 4,
        "lastPage": 7,
        "perPage": 3,
        "to": 6,
        "total": 21
    }
}
dxxyhpgq

dxxyhpgq2#

通过从您自己的集合EntityCollection创建此方法很简单:

public function paginationInformation($request, $paginated, $default)
{
    unset($default['links']);
    return $default;
}
a11xaf1n

a11xaf1n3#

这里的问题是ResourceCollection覆盖了您的自定义响应结构,并在这里添加了一些额外的属性。你可以通过重写toResponse()方法来修复这个(损坏的IMO)行为,如下所示:

/**
 * {@inheritdoc}
 */
public function toResponse($request)
{
    return JsonResource::toResponse($request);
}
8mmmxcuj

8mmmxcuj4#

我在试图做同样的事情时遇到了这个问题。在Laravel 8中,你似乎可以做到这一点,但你不能使用资源集合。您只需使用您创建的资源类。因此,在您的示例中,使用的不是EntityCollection,而是EntityResource
样品如下:

$results = EntityResource::collection(Entity::paginate($pageSize));

return response()->json([
    'data' => $results,
    'lastPage' => $results->lastPage()
]);

使用这种方法,您实际上是自己构建元数据。你可以参考Laravel的分页文档,看看还有哪些方法可以用来构建你自己的元数据。
https://laravel.com/docs/8.x/pagination

hfsqlsce

hfsqlsce5#

这对我来说一直是一个PIA。
您将找到的建议/答案将涉及创建多个集合,如果您使用错误的paginate方法,可能会出现未定义的键等。
我喜欢做的事情很简单,我在Eloquent Builder中添加了一个函数,所以你可以只做jsonPaginate()
app/Providers/AppServiceProvider.php

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;

public function boot()
{
    Builder::macro('jsonPaginate', function (int $perPage = 15) {
        /** @var Collection $this */
        $json = $this->paginate($perPage)->toArray();
        $json['meta'] = [
            'from'      => $json['from'],
            'to'        => $json['to'],
            'last_page' => $json['last_page'],
            'per_page'  => $json['per_page'],
            'total'     => $json['total'],
        ];
        unset(
            $json['links'],
            $json['path'],
            $json['prev_page_url'],
            $json['first_page_url'],
            $json['last_page_url'],
            $json['next_page_url'],
            $json['current_page'],
            $json['from'],
            $json['to'],
            $json['last_page'],
            $json['per_page'],
            $json['total'],
        );
        return $json;
    });
}

现在你可以像这样使用它:

Route::get('/', function () {
    return App\Models\User::jsonPaginate();
});

备注:

  • DocBlock是为了在从匿名函数/回调中抓取$this时绕过Intelephense错误。
  • 我在我的例子中使用了两个自定义,一个是将一些键“移动”到meta键中,另一个是删除不需要的键,您可以按照自己的方式进行自定义。

相关问题