自定义 Laravel 5.5 Api 资源集合分页
Customising Laravel 5.5 Api Resource Collection pagination
我一直在使用 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' 未来的功能。
为了解决它,我必须使用 Resource Collections 而不是 Resources:
However, if you need to customize the meta data returned with the collection, it will be necessary to define a resource collection
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
字段,手册只显示 [=15= 的示例] 我们发送未修改的集合(资源集合 允许我们更改元数据)。所以如果我们只使用 Resource 那么我们可以修改集合数据而不是元数据。
您还可以扩展 JsonResource、AnonymousResourceCollection、ResourceCollection,最后扩展 PaginatedResourceResponse
接受的答案对我不起作用(在 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
];
}
}
@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));
}
所以我发现在 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 class 附带一个 additional() 方法,它允许您指定在使用资源时希望成为响应一部分的任何其他数据:
Route::get('/get-taxes', function () {
$taxes = Taxes::paginate();
return new TaxCollection($s)->additional([
'pagination' => [
'total' => $taxes->total,
...
]
]);
});
我一直在使用 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' 未来的功能。
为了解决它,我必须使用 Resource Collections 而不是 Resources:
However, if you need to customize the meta data returned with the collection, it will be necessary to define a resource collection
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
字段,手册只显示 [=15= 的示例] 我们发送未修改的集合(资源集合 允许我们更改元数据)。所以如果我们只使用 Resource 那么我们可以修改集合数据而不是元数据。
您还可以扩展 JsonResource、AnonymousResourceCollection、ResourceCollection,最后扩展 PaginatedResourceResponse
接受的答案对我不起作用(在 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
];
}
}
@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));
}
所以我发现在 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 class 附带一个 additional() 方法,它允许您指定在使用资源时希望成为响应一部分的任何其他数据:
Route::get('/get-taxes', function () {
$taxes = Taxes::paginate();
return new TaxCollection($s)->additional([
'pagination' => [
'total' => $taxes->total,
...
]
]);
});