DataTables 中的服务器端处理 UTF-8 搜索

Posted

技术标签:

【中文标题】DataTables 中的服务器端处理 UTF-8 搜索【英文标题】:Server-side processing UTF-8 search in DataTables 【发布时间】:2017-06-16 12:42:15 【问题描述】:

我将 DataTables 与服务器端处理一起使用

$('#usersTable').DataTable(
            
                responsive: true,
                "pageLength": 20,
                "processing": true,
                "serverSide": true,
                "bLengthChange": true,
                "bSort" : false,
                "bInfo" : false,
                "aLengthMenu": [[20, 50, 75, -1], [20, 50, 75, "ყველა"]],
                "ajax": "helpers/server_processing.php"
            
        );

我还将ssp.class.php中的数据库连接更改为

$db = @new PDO(
"mysql:host=$sql_details['host'];dbname=$sql_details['db']",
$sql_details['user'],
$sql_details['pass'],
array( PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'" )
);

尝试在搜索栏中搜索 UTF-8 字符时仍然遇到问题

有人可以帮忙吗?

查询(从评论中复制)

SELECT  COUNT(`id`)
    FROM  `users`
    WHERE  (`id` LIKE :binding_0
              OR  `mac` LIKE :binding_1
              OR  `ip` LIKE :binding_2
              OR  `sname` LIKE :binding_3
              OR  `login` LIKE :binding_4
              OR  `tariff_plan_id` LIKE :binding_5
              OR  `now_playing_type` LIKE :binding_6
              OR  `now_playing_content` LIKE :binding_7
              OR  `now_playing_start` LIKE :binding_8
              OR  `keep_alive` LIKE :binding_9
              OR  `id` LIKE :binding_10
              OR  `status` LIKE :binding_11
           ) 
SELECT  COUNT(`id`)
    FROM  `users`
SELECT  `id`, `mac`, `ip`, `sname`, `login`, `tariff_plan_id`,
        `now_playing_type`, `now_playing_content`, `now_playing_start`,
        `keep_alive`, `id`, `status`
    FROM  `users`
    WHERE  (`id` LIKE :binding_0
              OR  `mac` LIKE :binding_1
              OR  `ip` LIKE :binding_2
              OR  `sname` LIKE :binding_3
              OR  `login` LIKE :binding_4
              OR  `tariff_plan_id` LIKE :binding_5
              OR  `now_playing_type` LIKE :binding_6
              OR  `now_playing_content` LIKE :binding_7
              OR  `now_playing_start` LIKE :binding_8
              OR  `keep_alive` LIKE :binding_9
              OR  `id` LIKE :binding_10
              OR  `status` LIKE :binding_11
           )
    ORDER BY  id ASC
    LIMIT  0, 20

编辑:附加信息

我发现带有 utf-8 值的 LIKE 查询不适用于 mysql 中的 DateTime 字段

但 DataTables 会自动将每个字段与搜索字符串进行比较。如果字符串包含 utf-8 字符,是否有一种简单的方法可以告诉 DataTables 不要搜索 DateTime 类型的列?

【问题讨论】:

看下面的答案***.com/a/31065121/617373,可能会有帮助 正如您在第二个代码块中看到的,我已经在我的 pdo 连接中插入了“set names utf8” 只是一个疯狂的猜测:数据库/某些表的排序规则设置不好,例如不是utf8。检查这个问题:***.com/questions/1008287/… 所有表的排序规则都设置为 utf8_general_ci 您能否显示 a) show full columns from your-table 的输出和 b) 引发该错误的查询? 【参考方案1】:

使用new PDO('dblib:host=host;dbname=db;charset=UTF8', $user, $pwd); 而不是ATTR_INIT_COMMAND

->set_charset 用于mysqli 接口,而不是PDO

根据图片,列是CHARACTER SET utf8 COLLATION utf8_general_ci,对于格鲁吉亚语来说已经足够了。

向我们展示带有 LIKE 的正在抱怨的查询。

问题与LIKE 语句有关。如果它在存储例程中,让我们看看SHOW CREATE ...创建时,可能是错误的字符集/排序规则生效。

正如this 的“最佳实践”部分所述,“html 表单应该以“开头”。检查那里的其他项目。

【讨论】:

以下是我可以从 ssp 记录的查询:pastebin.com/2xtB1DrP “绑定”是如何执行的?也许这就是字符集/排序规则搞砸的地方? 它使用 $stmt->bindValue( $binding['key'], $binding['val'], $binding['type'] );带有绑定数组pastebin.com/fNbhYYN7【参考方案2】:

试试这个:

$db_link = new PDO($dsn, $username, $password) // DB-connection

// CHARSET: utf8
$db_link->query('SET NAMES utf8');

【讨论】:

【参考方案3】:

如果搜索字符串为 utf-8,我通过更改 ssp.class.phpfilter 函数以从搜索中排除 DateTime 列来解决此问题

static function filter ( $request, $columns, &$bindings )

    $globalSearch = array();
    $columnSearch = array();
    $dtColumns = self::pluck( $columns, 'dt' );

    if ( isset($request['search']) && $request['search']['value'] != '' ) 
        $str = $request['search']['value'];

        for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) 
            $requestColumn = $request['columns'][$i];
            $columnIdx = array_search( $requestColumn['data'], $dtColumns );
            $column = $columns[ $columnIdx ];

            //**ADDED THIS**
            if(mb_detect_encoding($request["search"]["value"])=="UTF-8")
                if($column['db']=="keep_alive" || $column['db']=="now_playing_start")
                    continue;
                
            

            if ( $requestColumn['searchable'] == 'true' ) 
                $binding = self::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                $globalSearch[] = "`".$column['db']."` LIKE ".$binding;
            
        
    

    // Individual column filtering
    if ( isset( $request['columns'] ) ) 
        for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) 
            $requestColumn = $request['columns'][$i];
            $columnIdx = array_search( $requestColumn['data'], $dtColumns );
            $column = $columns[ $columnIdx ];

            $str = $requestColumn['search']['value'];

            if ( $requestColumn['searchable'] == 'true' &&
                $str != '' ) 
                $binding = self::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                $columnSearch[] = "`".$column['db']."` LIKE ".$binding;
            
        
    

    // Combine the filters into a single string
    $where = '';

    if ( count( $globalSearch ) ) 
        $where = '('.implode(' OR ', $globalSearch).')';
    

    if ( count( $columnSearch ) ) 
        $where = $where === '' ?
            implode(' AND ', $columnSearch) :
            $where .' AND '. implode(' AND ', $columnSearch);
    

    if ( $where !== '' ) 
        $where = 'WHERE '.$where;
    

    return $where;

【讨论】:

以上是关于DataTables 中的服务器端处理 UTF-8 搜索的主要内容,如果未能解决你的问题,请参考以下文章

使用 Datatables v1.10.0 进行服务器端处理

DataTables jQuery插件服务器端处理,通过ajax删除后智能分页

Datatables + PHP:多表的服务器端处理

在 DataTables 服务器端处理脚本中运行 MySQL 查询

dataTables .row( ) 不是功能服务器端处理行详细信息

dataTables .row( ) 不是功能服务器端处理行详细信息