PHP搜索表单问题:如何实现$code精确匹配与$name模糊匹配?
解决PHP搜索表单中精确匹配Code、模糊匹配Name的问题
你的问题核心在于当用户只填写一个字段时,另一个字段为空值会导致OR条件引入无效匹配规则,同时直接拼接SQL字符串还存在严重的SQL注入风险。我来帮你一步步解决这个问题:
问题根源分析
你原来的SQL语句:
SELECT * FROM list WHERE code = '$code' OR name = '%$name%' ORDER BY code
当用户只填写name时,$code会是空字符串(甚至可能是NULL),此时SQL会变成:
SELECT * FROM list WHERE code = '' OR name LIKE '%xxx%' ORDER BY code
如果你的code字段设置了NOT NULL约束,code = ''不会匹配任何记录,查询结果完全依赖name LIKE '%xxx%'——但如果变量处理不当(比如$name未正确获取、或包含未转义的特殊字符),就会导致无结果。更关键的是,这种直接拼接变量的写法极易被SQL注入攻击,风险极高。
正确解决方案:动态构建查询条件+预处理语句
我们需要仅针对用户填写的字段构建查询条件,同时使用预处理语句彻底规避SQL注入风险。
方案1:使用PDO(推荐,语法更简洁安全)
<?php // 1. 连接数据库(替换为你的数据库信息) $dsn = 'mysql:host=localhost;dbname=your_database;charset=utf8mb4'; $dbUser = 'your_username'; $dbPass = 'your_password'; try { $pdo = new PDO($dsn, $dbUser, $dbPass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch(PDOException $e) { die('数据库连接失败:' . $e->getMessage()); } // 2. 获取并过滤表单提交的参数 $code = trim($_POST['code'] ?? ''); $name = trim($_POST['name'] ?? ''); // 3. 初始化SQL语句和参数数组 $sql = 'SELECT * FROM list'; $params = []; // 4. 动态构建WHERE条件 if (!empty($code)) { // Code字段精确匹配 $sql .= ' WHERE code = ?'; $params[] = $code; } elseif (!empty($name)) { // Name字段模糊匹配 $sql .= ' WHERE name LIKE ?'; $params[] = "%{$name}%"; } // 5. 添加排序规则 $sql .= ' ORDER BY code'; // 6. 执行预处理查询 $stmt = $pdo->prepare($sql); $stmt->execute($params); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); // 处理查询结果(示例:打印结果) print_r($results); ?>
方案2:使用MySQLi
如果你习惯用MySQLi,也可以这样实现:
<?php // 1. 连接数据库 $conn = mysqli_connect('localhost', 'your_username', 'your_password', 'your_database'); if (!$conn) { die('数据库连接失败:' . mysqli_connect_error()); } mysqli_set_charset($conn, 'utf8mb4'); // 2. 获取并过滤参数 $code = trim($_POST['code'] ?? ''); $name = trim($_POST['name'] ?? ''); // 3. 初始化SQL和参数 $sql = 'SELECT * FROM list'; $params = []; $paramTypes = ''; // 4. 动态构建条件 if (!empty($code)) { $sql .= ' WHERE code = ?'; $params[] = $code; $paramTypes .= 's'; // 标记参数为字符串类型 } elseif (!empty($name)) { $sql .= ' WHERE name LIKE ?'; $params[] = "%{$name}%"; $paramTypes .= 's'; } $sql .= ' ORDER BY code'; // 5. 执行预处理查询 $stmt = mysqli_prepare($conn, $sql); if (!empty($params)) { mysqli_stmt_bind_param($stmt, $paramTypes, ...$params); } mysqli_stmt_execute($stmt); $result = mysqli_stmt_get_result($stmt); $results = mysqli_fetch_all($result, MYSQLI_ASSOC); // 处理结果 print_r($results); // 关闭连接 mysqli_close($conn); ?>
关键说明
- 动态条件构建:通过判断哪个字段有值,仅添加对应查询条件,彻底避免空字段带来的无效匹配。
- 预处理语句:用
?作为占位符,将参数与SQL语句分离,从根源上杜绝SQL注入风险。 - 参数过滤:用
trim()去除参数首尾空格,避免用户输入无意义空格导致的查询异常。
如果需要处理两个字段都为空的极端情况(虽然你说明用户不会这么操作),可以添加额外判断,返回空结果或提示用户输入查询条件。
内容的提问来源于stack exchange,提问作者jj jones
相关产品推荐
相关产品推荐

