Reputation: 77
In Laravel no way to replace the default structure for paginated responses. This is the structure I'm trying to achieve:
return response()->json([
'data' => $items->items()
'meta' => [
'current_page' => $items->currentPage(),
'from' => $items->firstItem(),
'last_page' => $items->lastPage(),
'per_page' => $items->perPage(),
'to' => $items->lastItem(),
'total' => $items->total(),
];
]);
Upvotes: 0
Views: 908
Reputation: 87
I've tried to implement paginationInformation()
directly into my Resource
, it's never calling the paginationInformation()
, any idea?
class SomeResource extends JsonResource
{
public function toArray(Request $request): array
{
//
}
public function paginationInformation($request, $paginated, $default)
{
dd("called");
}
}
Called by using:
public function index(Request $request, OrderFilter $filters)
{
return OrderResource::collection(Order::where('x', 'y')->paginate());
}
Upvotes: 0
Reputation: 489
In Laravel 10 (not sure since which version) you can implement method paginationInformation
on your ResourceCollection
(Laravel docs), where you can adjust default format of pagination data. I made class like this:
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
class PaginatedJsonResourceCollection extends AnonymousResourceCollection
{
/**
* Adjust pagination data format
*
* @param Request $request
* @param array $paginated
* @param array $default
* @return array
*/
public function paginationInformation(Request $request, array $paginated, array $default)
{
unset($default['links']);
$default['meta'] = [
'page' => $default['meta']['current_page'],
'lastPage' => $default['meta']['last_page'],
'perPage' => $default['meta']['per_page'],
'total' => $default['meta']['total']
];
return $default;
}
}
As you can see, I totally removed links
attribute from the response and adjusted meta
field to my needs.
Then I needed to tell Laravel to use this custom class when creating collections so I created PaginatedJsonResource
class:
use Illuminate\Http\Resources\Json\JsonResource;
class PaginatedJsonResource extends JsonResource
{
/**
* Create a new resource collection instance.
*
* @param mixed $resource
* @return PaginatedJsonResourceCollection
*/
protected static function newCollection($resource): PaginatedJsonResourceCollection
{
return new PaginatedJsonResourceCollection($resource, static::class);
}
}
And then made all my resources extend this class:
class ArticleResource extends PaginatedJsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
];
}
}
Now whenever I return in controller
return ArticleResource::collection(Article::paginate());
I get paginated data in my custom format:
{
"data": [
{
"id": 12345,
"title": "Article 1",
"content": "..."
},
{
"id": 12346,
"title": "Article 2",
"content": "..."
},
...
],
"meta": {
"page": 1,
"lastPage": 50,
"perPage": 15,
"total": 1000
}
}
Upvotes: 0
Reputation: 3045
I have solved this issue before with resource collection. This is not supported by Laravel out of the box so it needs a bit of work.
First, you got to override the App\Http\Resources\PaginatedResourceResponse
class, which is the default way to present paginated response. Then you can override the default structure of the returned paginated data.
class CustomPaginatedResourceResponse extends PaginatedResourceResponse
{
}
Then pls create a resource collection that uses the custom paginated resource.
class ItemsResource extends ResourceCollection
{
public function toArray($request)
{
}
// Override the toResponse method.
public function toResponse($request)
{
return $this->resource instanceof AbstractPaginator
? (new CustomPaginatedResourceResponse($this))->toResponse($request)
: parent::toResponse($request);
}
}
Finally, you can simply use the ItemsResource
in your controller.
return new ItemsResource($items);
This requires understanding of the api resources and the source code. Pls spend some time to read the docs and figure out how the App\Http\Resources\PaginatedResourceResponse
is used.
Upvotes: 1