Laravel接口返回分页数据出现data嵌套data问题如何解决
问题场景
- 项目trait中编写了统一接口成功响应方法,代码如下:
protected function success($message, $data , $status = Response::HTTP_OK) { return $data ? response()->json([ 'status' => 'success', 'message' => $message, 'data' => $data, ], $status) : response()->json([ 'status' => 'success', 'message' => $message, ], $status); }
- 调用该方法返回Laravel查询生成的客户分页数据时,出现双层
data嵌套问题:外层是自定义响应结构的data字段,内层是Laravel分页自带的data字段(存放实际列表数据),Postman接收到的原始响应结构如下:
{ "status": "success", "message": "Fetched customer details", "data": { "current_page": 1, "data": [ { "pid": "hkEH97ur", "name": "badri44", "email": "badri4@rtechsols.in", "mobile": "761487", "total_amount": 0, "used_amount": 0, "remaining_amount": 0, "active_status": "Active" }, { "pid": "5j9vCsRb", "name": "badri3", "email": "badri3@rtechsols.in", "mobile": "9989893890808118", "total_amount": 0, "used_amount": 0, "remaining_amount": 0, "active_status": "Active" } ], "first_page_url": "http://localhost/retail/v1/customers?page=1", "from": 1, "next_page_url": null, "path": "http://localhost/retail/v1/customers", "per_page": 15, "prev_page_url": null, "to": 2 } }
解决方案
推荐在统一响应层做类型判断,自动适配分页数据和普通数据,不需要在每个接口调用处单独处理,维护成本更低。
- 首先引入分页实例对应的接口类,改造原有
success方法,识别到分页传入时自动拆分列表数据和分页元信息:
use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Symfony\Component\HttpFoundation\Response; protected function success($message, $data = null, $status = Response::HTTP_OK) { $baseResponse = [ 'status' => 'success', 'message' => $message, ]; if (!is_null($data)) { // 匹配到分页实例时做结构拆分 if ($data instanceof LengthAwarePaginator) { $baseResponse['data'] = $data->items(); // 实际列表数据直接赋值给外层data // 分页元信息独立存放,和data平级 $baseResponse['pagination'] = [ 'current_page' => $data->currentPage(), 'per_page' => $data->perPage(), 'total' => $data->total(), 'last_page' => $data->lastPage(), 'from' => $data->firstItem(), 'to' => $data->lastItem(), 'has_more' => $data->hasMorePages() ]; } else { // 非分页数据按原有逻辑处理 $baseResponse['data'] = $data; } } return response()->json($baseResponse, $status); }
- 调整后的规范响应结构如下,无多余嵌套:
{ "status": "success", "message": "Fetched customer details", "data": [ { "pid": "hkEH97ur", "name": "badri44", "email": "badri4@rtechsols.in", "mobile": "761487", "total_amount": 0, "used_amount": 0, "remaining_amount": 0, "active_status": "Active" }, { "pid": "5j9vCsRb", "name": "badri3", "email": "badri3@rtechsols.in", "mobile": "9989893890808118", "total_amount": 0, "used_amount": 0, "remaining_amount": 0, "active_status": "Active" } ], "pagination": { "current_page": 1, "per_page": 15, "total": 2, "last_page": 1, "from": 1, "to": 2, "has_more": false } }
注意:不要直接修改Laravel框架底层的分页序列化规则来移除内层data字段,会影响框架内部其他场景对分页实例的正常调用,在响应出口层做转换是兼容性最高的方案。
如果不想修改全局统一响应方法,也可以在单个接口调用时手动拆分分页数据后再传入success方法,逻辑和上述全局处理一致。
内容的提问来源于stack exchange,提问作者badrinath
相关产品推荐
相关产品推荐

