You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 10:01:13