0

0

PHP与SQL多词多列模糊搜索优化及SQL注入防护指南

碧海醫心

碧海醫心

发布时间:2025-11-15 12:08:02

|

148人浏览过

|

来源于php中文网

原创

PHP与SQL多词多列模糊搜索优化及SQL注入防护指南

本教程详细阐述了如何在php和sql中实现对包含空格的多词多列模糊搜索功能。文章首先分析了传统`concat_ws`方法的局限性,继而提出了通过php拆分搜索词并在sql中使用多个`like`条件进行匹配的策略。更重要的是,教程强调并演示了如何利用php的预处理语句(prepared statements)彻底防范sql注入攻击,并探讨了在处理大规模数据时可能面临的性能问题及相应的优化方案,包括全文索引和专业搜索工具

在构建基于Web的数据库搜索功能时,用户经常需要通过一个输入框搜索多个字段,并且搜索词可能包含空格。例如,用户输入“test 2”,期望“test”匹配到firstName字段,“2”匹配到id字段。然而,直接使用CONCAT_WS函数拼接所有字段并进行LIKE '%search term%'匹配,对于这种多词多列的模糊搜索场景往往无法达到预期效果。

理解传统搜索的局限性

原有的CONCAT_WS函数旨在将多个字段的内容连接成一个字符串进行匹配。当搜索词中包含空格时,例如“test 2”,CONCAT_WS会尝试在连接后的完整字符串中查找“test 2”这个精确的子串。然而,如果“test”存在于firstName字段,“2”存在于id字段,并且它们之间并没有物理上的空格(因为它们是不同的字段),那么CONCAT_WS将无法匹配到预期的结果。这是因为CONCAT_WS默认会使用逗号作为分隔符(或者在CONCAT_WS(separator, str1, str2, ...)中指定的分隔符),而用户期望的是将搜索词的每个部分分别匹配到不同的字段中。

多词多列模糊搜索的实现策略

为了实现对包含空格的多词多列模糊搜索,我们需要将用户输入的搜索词拆分成独立的单词,然后针对每个单词,在数据库的多个相关列中分别进行模糊匹配。

PHP层处理:拆分搜索词

首先,在PHP代码中,我们需要获取用户输入的搜索字符串,并将其按照空格拆分成一个单词数组。

立即学习PHP免费学习笔记(深入)”;

Flowith
Flowith

一款GPT4驱动的节点式 AI 创作工具

下载
// 获取用户输入的搜索值
$valueToSearch = $_POST['valueToSearch'];

// 使用空格拆分搜索字符串
$searchWords = explode(' ', $valueToSearch);

// 过滤掉空字符串,以防用户输入多个连续空格
$searchWords = array_filter($searchWords);

SQL层构建查询:使用多个LIKE条件

接下来,我们需要根据这些拆分出的单词来构建SQL的WHERE子句。对于每个单词,我们都应该在所有需要搜索的列中应用LIKE '%word%'条件。为了实现更灵活的匹配,通常我们会为每个搜索词生成一个子条件组,例如 (column1 LIKE '%word%' OR column2 LIKE '%word%'),然后将这些子条件组通过 AND 逻辑连接起来,以确保所有搜索词都能在某些列中找到匹配。

$conditions = [];
foreach ($searchWords as $word) {
    // 为每个单词构建一个子条件组,在所有相关列中搜索
    $wordConditions = [];
    // 定义需要搜索的列
    $columnsToSearch = ['id', 'office', 'firstName', 'lastName', 'type', 'status', 'deadline', 'contactPref', 'email', 'phoneNumber', 'taxPro']; 

    foreach ($columnsToSearch as $column) {
        $wordConditions[] = "`" . $column . "` LIKE ?"; // 使用占位符
    }
    // 将一个单词的所有列条件用 OR 连接
    $conditions[] = "(" . implode(" OR ", $wordConditions) . ")";
}

// 将所有单词的条件用 AND 连接
$whereClause = "";
if (!empty($conditions)) {
    $whereClause = " WHERE " . implode(" AND ", $conditions);
}

// 完整的查询语句结构
$query = "SELECT * FROM `master`" . $whereClause;

核心安全实践:防范SQL注入

在原始代码中,直接将用户输入 $valueToSearch 拼接到SQL查询字符串中 (LIKE '%".$valueToSearch."%') 存在严重的SQL注入漏洞。恶意用户可以构造特殊的输入来修改或破坏数据库查询,从而获取敏感信息或篡改数据。

强烈建议使用预处理语句(Prepared Statements)来防范SQL注入。 预处理语句将SQL查询的结构与数据分离,数据库服务器会在执行前编译查询结构,然后将数据作为参数绑定进去,从而避免了恶意代码的执行。

使用预处理语句的示例代码

以下是结合上述多词搜索逻辑和预处理语句的改进示例:

error));
    }

    if (!empty($params)) {
        // 's' for string, 'i' for integer, 'd' for double, 'b' for blob
        // 这里所有搜索词都按字符串处理,所以类型字符串是 'sss...'
        mysqli_stmt_bind_param($stmt, $paramTypes, ...$params);
    }

    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt); // 获取结果集
    mysqli_stmt_close($stmt);
    mysqli_close($connect);
    return $result;
}

// 处理搜索逻辑
if(isset($_POST['search']))
{
    $valueToSearch = $_POST['valueToSearch'];
    $searchWords = explode(' ', $valueToSearch);
    $searchWords = array_filter($searchWords); // 过滤空字符串

    $conditions = [];
    $params = [];
    $paramTypes = ''; // 用于存储参数类型字符串

    $columnsToSearch = ['id', 'office', 'firstName', 'lastName', 'type', 'status', 'deadline', 'contactPref', 'email', 'phoneNumber', 'taxPro'];

    foreach ($searchWords as $word) {
        $wordConditions = [];
        foreach ($columnsToSearch as $column) {
            $wordConditions[] = "`" . $column . "` LIKE ?";
            $params[] = '%' . $word . '%'; // 绑定参数时添加通配符
            $paramTypes .= 's'; // 所有搜索词都作为字符串处理
        }
        $conditions[] = "(" . implode(" OR ", $wordConditions) . ")";
    }

    $whereClause = "";
    if (!empty($conditions)) {
        $whereClause = " WHERE " . implode(" AND ", $conditions);
    }

    $query = "SELECT * FROM `master`" . $whereClause;
    $search_result = filterTable($query, $params, $paramTypes);

} else {
    $query = "SELECT * FROM `master`";
    $search_result = filterTable($query); // 无参数查询
}

// HTML 部分
?>

    
        PHP HTML TABLE DATA SEARCH
        
    
    

        




相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2036

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1368

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1279

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

949

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1406

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1231

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1440

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1303

2023.11.13

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.6万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 779人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号

ID Office First Name Last Name Type Status Deadline