PHP怎样搜索数据库_PHP模糊查询语句【搜索】
PHP模糊查询应使用预处理防止SQL注入,通配符置于参数值而非SQL模板。需统一字符集为`utf8mb4`。大数据量下避免`LIKE'%关键词%'`,改用前缀匹配、全文索引或外部搜索引擎,并对特殊字符用`ESCAPE`转义。
数据库模糊查询是PHP开发中再常见不过的需求,但很多人写出来的搜索代码在线上总会出点这样那样的小问题。这里有几个实战中容易踩的坑,以及经过验证的正确写法,直接说关键的。
PHP中用LIKE做模糊查询的正确姿势
直接拼接用户输入到SQL里是危险的,这一点怎么强调都不过分。使用`mysqli_query()`或`pdo-query()`配合`LIKE`时,必须走预处理。一个典型的错误是写成`"%{$_GET['q']}%"`,这等于把SQL注入的大门敞开了。
关键点在于通配符要放在参数值里,而不是SQL模板里——绑定参数时传`'%' . $keyword . '%'`,而不是在SQL里写`LIKE '%?%'`。中文搜索尤其要注意,数据库和连接的字符集必须一致,否则明明有数据却查不出来。检查一下`SET NAMES utf8mb4`是否已执行,表字段是否设置了`utf8mb4_unicode_ci`这类排序规则。另外,`LIKE`是否区分大小写取决于字段的collation,如果需要不区分,可以用`utf8mb4_general_ci`,或者显式地用`LOWER()`函数包裹字段和参数。
PDO预处理:安全模糊搜索的最小可行示例
下面这段代码是能直接跑通、且不遗漏关键步骤的写法:
$pdo = new PDO("mysql:host=localhost;dbname=test;charset=utf8mb4", $user, $pass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$keyword = $_GET['q'] ?? '';
$stmt = $pdo->prepare("SELECT id, title FROM article WHERE title LIKE ?");
$stmt->execute(['%' . $keyword . '%']);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
注意几个细节:`charset=utf8mb4`必须写在DSN里;`PDO::ATTR_ERRMODE`要设为异常模式,否则错误会被静默处理;`execute()`的参数是个数组,即使只有一个值也要用`[]`包起来。
什么时候不该用LIKE——性能与替代方案
当数据量超过10万行时,`LIKE '%关键词%'`会导致全表扫描,索引完全失效。这时候需要重新审视方案:
- 如果查询可以改成前缀匹配(`LIKE '关键词%'`),还能走B-tree索引,但中间或后缀匹配就不行。
- 需要全文检索语义,比如相关性排序或同义词匹配,应该改用MySQL的`MATCH() AGAINST()`,前提是字段已经建立了FULLTEXT索引。
- 更复杂的搜索场景,建议直接接入Elasticsearch或Meilisearch,PHP端通过HTTP请求对接,别硬扛。
MySQL中LIKE的转义问题怎么处理
如果用户搜索的内容包含`%`或`_`(比如查文件名`report_2024.sql`),这些字符默认会被当成通配符处理,结果自然不对。解决方法是指定一个ESCAPE字符:
SELECT * FROM logs WHERE content LIKE '%report_2024%' ESCAPE '\';
对应的PDO写法:
$stmt = $pdo->prepare("SELECT * FROM logs WHERE content LIKE ? ESCAPE ?");
$stmt->execute(["%report_2024%", '\\']);
这里要注意,反斜杠在PHP字符串里需要双写`'\\'`,而且必须在绑定时传入,不能写死在SQL里——否则换个数据库就可能出问题。
说到底,模糊查询真正难的不是语法,而是那些边界情况:空输入、超长输入、特殊字符、编码错位、索引没生效却以为是代码太慢。这些地方只要漏掉一个,线上就可能出问题。


































