DataTables加载5万+行数据失败,如何对接现有接口实现服务端处理
DataTables服务端模式适配不可修改的内部Web Service解决方案
核心实现思路
- 新增PHP中间代理层,前端DataTables的请求地址改为该代理层,原有查询参数
tipo、dias_reco照常传递 - 代理层接收DataTables服务端模式的分页、排序、搜索参数,调用原有cURL逻辑请求内部Web Service获取全量数据
- 代理层在本地对全量数据做搜索过滤、排序、分页处理后,返回符合DataTables服务端协议的JSON格式
- 原内部Web Service无需做任何修改,原有业务逻辑完全保留
第一步:修改前端DataTables初始化配置
仅需新增服务端模式配置,调整ajax参数传递逻辑,原有列配置、渲染逻辑完全不变:
let $tabla = jQuery("#datatable-buscador"); $tabla.dataTable().fnDestroy(); $tabla.dataTable({ "scrollX": true, "lengthMenu": [[15, 25, 30, -1], [15, 25, 30, "All"]], "lengthChange": false, "order": [1, "desc"], "language": { "url": "/src_reconocimientos/includes/js/utils/spanish.json" }, // 新增开启服务端模式 "serverSide": true, "processing": true, // 可选,展示加载状态提示 "ajax": { // 改为中间代理层地址 url: "/example/dt_proxy.php", type: "POST", dataType: "JSON", // 合并DataTables默认参数和自定义业务参数 data: function (d) { d.tipo = tipo; d.dias_reco = diasReco; }, timeout: 180000 //3 min }, "createdRow": function (row, data, dataIndex) { jQuery(row).attr("id", data.N_RECONOCIMIENTO); }, "columnDefs": [ { targets: [0, 1, 2, 4, 5, 7, 8], className: 'dt-body-center' }, ], "columns": [ { "data": "N_RECONOCIMIENTO" },// 0 { "data": null, render: function (data, type, full, meta) { return formatFecha(data.FECHA_RECONOCIMIENTO); } }, //1 { "data": "DNI" }, // 2 { "data": "NOMBRE_TRABAJADOR" }, // 3 { "data": "EMPRESA" }, // 4 { "data": "REF_INTERNA" }, // 5 { "data": "NOMBRE_CLIENTE" }, // 6 { "data": "VISADO" }, // 7 { "data": "PROP" }, // 8 ] });
第二步:新增PHP中间代理层dt_proxy.php
直接复用你原有cURL调用内部Web Service的逻辑即可,完整代码如下:
<?php // 接收前端传递参数 $draw = intval($_POST['draw']); $start = intval($_POST['start']); $length = intval($_POST['length']); $search = $_POST['search']['value'] ?? ''; $order = $_POST['order'] ?? []; $columns = $_POST['columns'] ?? []; // 原有业务参数 $tipo = $_POST['tipo'] ?? ''; $dias_reco = $_POST['dias_reco'] ?? ''; // --------------- 复用原有cURL调用内部接口逻辑 --------------- $ch = curl_init(); // 替换为你实际的内部Web Service地址 curl_setopt($ch, CURLOPT_URL, "内部Web Service实际请求地址"); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([ 'tipo' => $tipo, 'dias_reco' => $dias_reco ])); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); $all_data = json_decode($response, true)['data'] ?? []; // ----------------------------------------------------------- $recordsTotal = count($all_data); $recordsFiltered = $recordsTotal; // 处理搜索过滤,可根据需求增减需要搜索的字段 if (!empty($search)) { $all_data = array_filter($all_data, function ($item) use ($search) { return stripos((string)$item['N_RECONOCIMIENTO'], $search) !== false || stripos($item['NOMBRE_TRABAJADOR'], $search) !== false || stripos($item['NOMBRE_CLIENTE'], $search) !== false || stripos($item['DNI'], $search) !== false; }); $recordsFiltered = count($all_data); } // 处理排序 if (!empty($order)) { $order_column = $columns[$order[0]['column']]['data']; $order_dir = $order[0]['dir']; usort($all_data, function ($a, $b) use ($order_column, $order_dir) { if ($a[$order_column] == $b[$order_column]) return 0; $res = $a[$order_column] < $b[$order_column] ? -1 : 1; return $order_dir == 'asc' ? $res : -$res; }); } // 处理分页 if ($length != -1) { $all_data = array_slice($all_data, $start, $length); } // 返回符合DataTables要求的格式 echo json_encode([ 'draw' => $draw, 'recordsTotal' => $recordsTotal, 'recordsFiltered' => $recordsFiltered, 'data' => array_values($all_data) ]); ?>
注意事项
- 5万条数据量级下,PHP内存处理完全无压力,如遇内存不足可调整php.ini的
memory_limit参数 - 搜索、排序的字段可根据实际业务需求自行增减调整
- 如果后续内部Web Service迭代支持分页、搜索、排序参数,可直接修改中间层逻辑传递对应参数,无需修改前端代码,性能会进一步提升
内容的提问来源于stack exchange,提问作者Jesus91
相关产品推荐
相关产品推荐

