如何通过Yajra Laravel向API传递页码实现手动分页?
实现Yajra DataTables结合API的手动分页方案
要解决一次性加载6000条数据的问题,我们需要实现服务器端分页:让Yajra DataTables点击分页时,向API传递页码参数,API返回对应页的数据,而非全部数据。以下是具体实现步骤:
1. 修改API接口,支持分页参数
更新API的index方法,接收分页参数并返回分页数据及元信息(总记录数、当前页等):
public function index(Request $request) { // 接收前端传递的分页参数,默认每页10条 $perPage = $request->get('per_page', 10); $page = $request->get('page', 1); // 使用Laravel的paginate方法实现数据库分页 $products = Product::where('coid', $this->user->coid) ->with('group', 'unit', 'category', 'brand', 'department', 'variants','color','size' ,'createdBy') ->orderBy('created_at', 'DESC') ->paginate($perPage, ['*'], 'page', $page); return response()->json([ 'status' => 200, 'products' => $products->items(), // 当前页的数据 'total' => $products->total(), // 总记录数 'per_page' => $products->perPage(), // 每页条数 'current_page' => $products->currentPage(), // 当前页码 'last_page' => $products->lastPage() // 最后一页页码 ]); }
2. 修改消费端代码,传递分页参数并处理响应
更新消费端的index方法,从DataTables请求中提取分页参数,传递给API,并将API返回的分页元信息同步给Yajra DataTables:
public function index(Request $request) { if ($request->ajax()) { // 提取DataTables自带的分页参数 $start = $request->get('start', 0); $length = $request->get('length', 10); $page = ($start / $length) + 1; // 计算当前页码 // 向API传递分页参数 $response = Http::accept('application/json') ->withHeaders(['Authorization' => 'Bearer ' . $this->token]) ->get($this->apiurl . '/products', [ 'page' => $page, 'per_page' => $length ]); $responseData = json_decode($response); if ($responseData->status != 200) { return Datatables::of([])->make(true); } // 渲染DataTables,同步分页元信息 return Datatables::of($responseData->products) ->addIndexColumn() ->addColumn('action', function ($row) { $btn = '<div class="btn-group mb-5">' . '<button type="button" class="waves-effect waves-light btn btn-primary btn-sm dropdown-toggle" data-bs-toggle="dropdown">Action</button>' . '<div class="dropdown-menu">' . '<a href="' . route("products.edit", $row->id) . '" data-type="products" id="edtbtn-' . $row->id . '" class="dropdown-item" data-bs-original-title="Edit"><i class="ti-marker-alt"></i> Edit</a>' . '<a href="' . route("productview", $row->id) . '" data-type="products" class="dropdown-item" data-bs-original-title="Edit"><i class="ti-eye"></i> View</a>' . '<a href="' . route("drawbc", $row->bc) . '" target="_blank" class="dropdown-item" data-bs-original-title="Edit"><i class="ti-layout-column3-alt"></i>barcode label</a>' . '<a href="javascript:void(0)" id="dltbtn-' . $row->id . '" data-type="products" class="text-danger dropdown-item deltbtn" data-bs-original-title="Delete" data-bs-toggle="tooltip"><i class="ti-trash"></i> Delete</a>' . '</div>' . '</div>'; return $btn; }) ->addColumn('active', function ($row) { $actclass = $row->isact == 1 ? 'active' : ''; $boolclass = $row->isact == 1 ? 'true' : 'false'; $html = '<button type="button" aria-id="productid-' . $row->id . '" class="btn btn-sm btn-toggle ' . $actclass . ' activate" data-bs-toggle="button" aria-pressed="' . $boolclass . '" data-on-text="active" data-off-text="Inactive" autocomplete="off"><div class="handle"></div></button>'; return $html; }) ->addColumn('color', function ($row) { return isset($row->color) ? $row->color->nm : '-'; }) ->addColumn('size', function ($row) { return isset($row->size) ? $row->size->nm : '-'; }) ->rawColumns(['action', 'active']) // 设置总记录数和过滤后记录数(无过滤时两者一致) ->withTotalRecords($responseData->total) ->withFilteredRecords($responseData->total) ->make(true); } // 以下非AJAX逻辑保持不变 $response = Http::accept('application/json')->withHeaders( [ 'Authorization' => 'Bearer ' . $this->token ] )->get($this->apiurl . '/attributes'); $response = json_decode($response); $attributes = []; if ($response->status == 200) { $attributes = $response->attributes; } $data = Http::accept('application/json')->withHeaders( [ 'Authorization' => 'Bearer ' . $this->token ] )->get($this->apiurl . '/productprequisites'); $data = json_decode($data); if ($response->status == 200) { $groups = $data->groups; $categories = $data->categories; $departments = $data->departments; $units = $data->units; $brands = $data->brands; $qualities = $data->qualities; $acquiretypes = $data->acquiretypes; $agegroups = $data->agegroups; $seasons = $data->seasons; } return view('product.list', compact('attributes', 'brands', 'units', 'departments', 'categories', 'groups', 'seasons', 'acquiretypes', 'qualities', 'agegroups')); }
3. 前端DataTables开启服务器端模式
确保前端初始化DataTables时开启serverSide: true,这样才会自动发送分页、排序等参数到后端:
$(document).ready(function() { $('#products-table').DataTable({ processing: true, serverSide: true, // 关键:启用服务器端分页 ajax: "{{ route('products.index') }}", columns: [ { data: 'DT_RowIndex', name: 'DT_RowIndex' }, // 根据你的实际字段配置其他列 { data: 'name', name: 'name' }, { data: 'color', name: 'color' }, { data: 'size', name: 'size' }, { data: 'active', name: 'active', orderable: false, searchable: false }, { data: 'action', name: 'action', orderable: false, searchable: false } ] }); });
核心说明
- API端利用Laravel的
paginate()方法自动处理数据库分页,避免一次性加载全部数据 - 消费端通过DataTables传递的
start和length参数计算页码,实现分页请求 - Yajra DataTables通过
withTotalRecords()同步总记录数,确保前端分页控件正常生成
内容的提问来源于stack exchange,提问作者khubaib khan
相关产品推荐
相关产品推荐

