如何将 DataTable 中的单个列搜索与服务器端处理一起使用?

Posted

技术标签:

【中文标题】如何将 DataTable 中的单个列搜索与服务器端处理一起使用?【英文标题】:How to use individual column searching in DataTable with server-side processing? 【发布时间】:2021-08-27 14:02:58 【问题描述】:

我正在处理一个包含大量数据的项目。我已经使用服务器端处理来快速处理或加载数据。但是我的老板想在每一列中添加搜索,我尝试使用 multi filter 但数据没有改变。我该如何解决这个问题?

这是我从数据库中加载数据的表:

<table class="table table-bordered responsive nowrap" id="example" >    
    <thead> 
        <tr>
            <th >No</th>
            <th >Machine</th>
            <th >Spec1</th>
            <th >Spec2</th>
            <th >Spec3</th>
            <th >Spec4</th>
            <th >Spec5</th>
            <th >Spec6</th>
            <th >Qty</th>
            <th></th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th >No</th>
            <th >Machine</th>
            <th >Spec1</th>
            <th >Spec2</th>
            <th >Spec3</th>
            <th >Spec4</th>
            <th >Spec5</th>
            <th >Spec6</th>
            <th >Qty</th>
            <th></th>
        </tr>
    </tfoot>
</table>

这是我使用 php 和 AJAX 从 mysql 加载数据的脚本。我已经在 ajax 之后添加了多过滤器脚本,但仍然无法正常工作。

$(document).ready(function()
  //Reading
    var dataTable=$('#example').DataTable(
        "processing": true,
        "serverSide":true,
        "ajax":
            url:"pages_exe/machine_dt.php",
            type:"POST"
        ,
        initComplete: function () 
            this.api().columns().every( function () 
                var column = this;
                var select = $('<select><option value=""></option></select>')
                    .appendTo( $(column.footer()).empty() )
                    .on( 'change', function () 
                        var val = $.fn.dataTable.util.escapeRegex(
                            $(this).val()
                        );
 
                        column
                            .search( val ? '^'+val+'$' : '', true, false )
                            .draw();
                     );
 
                column.data().unique().sort().each( function ( d, j ) 
                    select.append( '<option value="'+d+'">'+d+'</option>' );
                 );
             );
        
    );
);

这是从我的数据库加载或获取数据的 PHP 文件。 machine_dt.php

<?php
include '../environment.php';
include '../config/database.php';

$request=$_REQUEST;
$col =array(
    0   =>  'machid',
    1   =>  'machine',
    2   =>  'spec1',
    3   =>  'spec2',
    4   =>  'spec3',
    5   =>  'spec4',
    6   =>  'spec5',
    7   =>  'spec6',
    8   =>  'qty'
);  //create column like table in database

$sql =" SELECT * FROM machinelist
        /*WHERE qty != 'disable'*/
        ORDER BY machine ASC;";
$query=mysqli_query($db,$sql);

$totalData=mysqli_num_rows($query);

$totalFilter=$totalData;

//Search
$sql =" SELECT * FROM machinelist
        /*WHERE qty != 'disable'*/
        WHERE 1=1
        ";

if(!empty($request['search']['value']))
    $sql.=" AND (machine Like '%".$request['search']['value']."%' ";
    $sql.=" OR brand Like '%".$request['search']['value']."%' ";
    $sql.=" OR spec2 Like '%".$request['search']['value']."%' ";
    $sql.=" OR spec3 Like '%".$request['search']['value']."%' ";
    $sql.=" OR spec4 Like '%".$request['search']['value']."%'";
    $sql.=" OR spec5 Like '%".$request['search']['value']."%' ";
    $sql.=" OR spec6 Like '%".$request['search']['value']."%' ";
    $sql.=" OR qty Like '%".$request['search']['value']."%' )";

$query=mysqli_query($db,$sql);
$totalData=mysqli_num_rows($query);

//Order
$sql.=" ORDER BY ".$col[$request['order'][0]['column']]."   ".$request['order'][0]['dir']."  LIMIT ".
    $request['start']."  ,".$request['length']."  ";

$query=mysqli_query($db,$sql);

$data=array();
$i=1;
while($row=mysqli_fetch_array($query))
    $subdata=array();

    $subdata[]= $i++;
    $subdata[]=$row[1]; 
    $subdata[]=$row[2]; 
    $subdata[]=$row[3]; 
    $subdata[]=$row[4]; 
    $subdata[]=$row[5];  
    $subdata[]=$row[6]; 
    $subdata[]=$row[7];
    $subdata[]=$row[8];
    $subdata[]='<button type="button" class="btn btn-primary btn-sm" id="update" data-id="'.$row[0].'" >Edit</button>
                <button type="button" class="btn btn-danger btn-sm" id="delete" data-id="'.$row[0].'" >Delete</button>';
    $data[]=$subdata;


$json_data=array(
    "draw"              =>  intval($request['draw']),
    "recordsTotal"      =>  intval($totalData),
    "recordsFiltered"   =>  intval($totalFilter),
    "data"              =>  $data
);

echo json_encode($json_data);

?>

【问题讨论】:

当您使用服务器端模式时,客户端过滤被禁用。相反,draw() 调用(您仍然需要)将触发数据发送到服务器。 DataTables 会自动为您执行此操作。因此,您应该会在该请求中看到任何选定的下拉值 - 例如,在 columns[2][search][value] 中。请参阅 "Sent Parameters" 以获取作为请求一部分的字段的完整列表。 所以,问题是:您是否在这些请求字段中看到您选择的下拉值?在您的浏览器工具中查看请求 (F12)。 您不应该将用户输入直接放入 sql 语句中,否则您的网站很快就会被黑客入侵(请参阅SQL Injection)。您可以通过使用 PHP 中的 PDO 数据库接口或使用 PHP 代码过滤记录而不是在末尾添加有点笨拙的 AND 子句来解决此问题。 【参考方案1】:
$sql.=" AND (machine Like '%".$request['search']['value']."%' ";
$sql.=" OR brand Like '%".$request['search']['value']."%' ";
$sql.=" OR spec2 Like '%".$request['search']['value']."%' ";
$sql.=" OR spec3 Like '%".$request['search']['value']."%' ";
$sql.=" OR spec4 Like '%".$request['search']['value']."%'";
$sql.=" OR spec5 Like '%".$request['search']['value']."%' ";
$sql.=" OR spec6 Like '%".$request['search']['value']."%' ";
$sql.=" OR qty Like '%".$request['search']['value']."%' )";

对于玩具项目来说没问题。但它不会超过一千行。

如果您的老板需要大规模的灵活性和绩效,那么您需要将问题改成类似

如何有效地对多列进行文本搜索?

对于该问题,您将看到一个讨论 FULLTEXT 索引并将列组合成一个列。

【讨论】:

我在这里看到 SQL 注入了吗?用户直接输入 SQL?至少请添加一个警告,说明这应该在以前以某种方式完成。

以上是关于如何将 DataTable 中的单个列搜索与服务器端处理一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

无法按 DataTable 中的列显示过滤器

如果整个列数据与搜索字符串匹配,如何在jQUERY Datatable中显示/搜索数据?

如何将两个 DataTable 与内部连接连接在一起

jQuery DataTable 自定义按钮正则表达式列搜索

如何使用 Vue.js 将 DataTable() 与数组中的数据(v-for 循环)附加到现有的 HTML <table>?

Phalcon PHP:Jquery Datatable Server Side 单个列过滤仅提供首页选择选项