Laravel 默认分页为我提供了默认分页格式的响应,但我想删除页面响应中元对象中的链接
我使用下面的代码来获取页面数据:
public function index()
{
return response()->json(
new EntityCollection(Entity::paginate($pageSize))
);
}
它返回我在代码中称为 EntityCollection 的资源集合中的响应。但我想删除响应中元数据中的链接。
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
}
}
请给我删除元中链接的方法或在 Laravel 中自定义分页响应的最佳实践。
我的解决方案:
<?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
}
}
通过从您自己的集合 EntityCollection 创建此方法很简单:
public function paginationInformation($request, $paginated, $default)
{
unset($default['links']);
return $default;
}
这对我来说始终是一个 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();
});
PS:
$this
时出现的 Intelephense 错误。meta
键中,另一种是删除不需要的键,您可以按照自己想要的方式对其进行自定义。这里的问题是
ResourceCollection
覆盖了您的自定义响应结构并添加了一些额外的属性here。您可以通过重写 toResponse()
方法来修复此(损坏的 IMO)行为,如下所示:
/**
* {@inheritdoc}
*/
public function toResponse($request)
{
return JsonResource::toResponse($request);
}
我在尝试做同样的事情时遇到了这个问题。使用 Laravel 8,似乎可以做到这一点,但不能使用资源集合。您只需使用您创建的资源类即可。因此,在您的情况下,您不使用
EntityCollection
,而是使用 EntityResource
示例如下:
$results = EntityResource::collection(Entity::paginate($pageSize));
return response()->json([
'data' => $results,
'lastPage' => $results->lastPage()
]);
通过这种方法,您基本上可以自己构建元数据。您可以参考 Laravel 的分页文档,了解还有哪些其他方法可用于构建您自己的元数据。
我在查询表单
paginate()
类中调用了 repository
。我收到了分页回复。因此,我需要在 query level
上处理分页,而不是在 resource response
层中处理分页。即
User::where('user_type', 'attendee')->paginate()
$attendees = $this->userRepository->getAttendees($filters);
$attendees = (AttendeeResource::collection($attendees))->response()->getData(true);
当我们使用上述语法调用资源时,它会在幕后调用
AnonymousResourceCollection
类。因此,要全局覆盖分页数据,而不是在多个 Resources
或覆盖 Resource
类中重复相同的内容。我创建了一个 macro
并介绍了我的分页格式。
AnonymousResourceCollection::macro('paginationInformation', function ($request, $paginated, $default) {
unset($default['links'], $default['meta']['links']);
return $default;
});
<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class AttendeeResource extends JsonResource
{
public function __construct($resource)
{
parent::__construct($resource);
self::wrap("users");
}
public function toArray(Request $request): array
{
return parent::toArray($request);
}
}