我一直在使用 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的功能。
为了解决这个问题,我必须使用资源集合而不是资源:
但是,如果需要自定义随集合返回的元数据,则需要定义资源集合
php artisan make:resource Tax --collection
或
php artisan make:resource TaxCollection
路线:
Route::get('/get-taxes', function () {
$taxes = Taxes::paginate();
return new TaxCollection($taxes);
});
税收.php:
<?php
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
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
示例(资源集合允许我们更改元数据)。因此,如果我们只使用资源,那么我们可以修改集合数据,但不能修改元数据。
接受的答案对我不起作用(在 Laravel 5.6 中),但我找到了更好的方法恕我直言。
将分页信息保存在资源集合构造函数中,并将分页器资源替换为基础集合。
税收征收.php:
namespace AppHttpResources;
use IlluminateHttpResourcesJsonResourceCollection;
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
];
}
}
所以我发现在 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,AnonymousResourceCollection,ResourceCollection和最后的PaginatedResourceResponse
> @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));
}
JsonResource 类附带了一个 extraal() 方法,它允许您指定在使用资源时要成为响应一部分的任何其他数据:
Route::get('/get-taxes', function () {
$taxes = Taxes::paginate();
return new TaxCollection($s)->additional([
'pagination' => [
'total' => $taxes->total,
...
]
]);
});
投票最多的答案对我不起作用(Laravel 10)。我需要在setData
之前删除json_encode
TaxCollection.php
use IlluminateHttpResourcesJsonResourceCollection;
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));
}
// Using Laravel 10
public function withResponse($request, $response)
{
$jsonResponse = json_decode($response->getContent(), true);
unset($jsonResponse['links'],$jsonResponse['meta']);
$response->setContent($jsonResponse); // remove json_encode
}
}
在控制器中添加以下内容
return response()->json([
'data' => resource_collection(BookResource::collection(Book::all())),
]);
您可以通过这样的帮助程序函数来做到这一点
function resource_collection($resource): array
{
return json_decode($resource->response()->getContent(), true) ?? [];
}