mysqli_real_escape_string 是对用户输入字符串进行转义以防止 sql 注入的函数,它在单引号、反斜杠等特殊字符前加反斜杠,但仅适用于字符串参数且依赖正确字符集和有效数据库连接。

mysqli_real_escape_string 是干什么的?
它就是给用户输入“消毒”的——把字符串里可能被 MySQL 当成 SQL 语法的字符(比如单引号、反斜杠、换行符)前面加个 ,让数据库老老实实把它当普通文本处理,而不是执行命令。
这招能拦住大部分基础 SQL 注入,但前提是:你得用对,而且只在拼接 SQL 字符串时才有效。
- 必须传入有效的
$mysqli连接对象,否则直接报错或返回空 - 转义结果只对当前连接的字符集生效;如果连接用的是
utf8mb4,但你没显式设置,可能漏掉多字节边界问题 - 它不处理
%和_—— 这俩在LIKE查询里是通配符,不手动转义的话,用户输个%就可能查出不该看到的数据
怎么用才不出错?
别跳过连接检查,也别图省事写成全局函数调用:
// ✅ 正确:有连接、有上下文、有判断
if ($mysqli && $mysqli->ping()) {
$safe_name = $mysqli->real_escape_string($_POST['name']);
$sql = "SELECT * FROM users WHERE name = '$safe_name'";
}
<p>// ❌ 错误:$mysqli 没初始化就调用
$safe_name = $mysqli->real_escape_string($input); // 致命错误:Call to a member function real_escape_string() on null</p><p>// ❌ 错误:忘记加引号,或者引号位置错
$sql = "WHERE name = $safe_name"; // 没引号 → 语法错误 or 注入风险
$sql = 'WHERE name = "' . $safe_name . '"'; // 引号类型混用,易出错-
mysqli::real_escape_string()是实例方法,不是静态函数,不能脱离对象调用 - 输入为空字符串、
null或非字符串时,它会静默转成空字符串,不报错但逻辑可能跑偏 - 如果连接断了,
real_escape_string()可能返回false,记得判空
为什么现在不推荐单独靠它防注入?
因为它只是“把危险字符藏起来”,而不是“把代码和数据彻底分开”。
一旦你在拼 SQL 时漏掉一个
real_escape_string(),整条语句就破防它没法保护数字型参数(比如
id=123),因为数字不用引号,也不需要转义,但恶意输入123 OR 1=1仍能生效字符集配置错(比如连接设
utf8,但字段是utf8mb4),某些四字节 emoji 会被截断或引发乱码,转义也可能失效更稳的方式是改用预处理语句:
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?"),然后bind_param()如果必须拼 SQL(比如动态表名、排序字段),那
real_escape_string()仅适用于字符串值,其他部分要用白名单校验,不能靠转义
LIKE 查询里怎么安全用?
mysqli_real_escape<em>string()</em> 默认不管 % 和 ,但用户搜 “a%b” 时,你又想让它原样匹配,就得额外处理:
// 手动补上 LIKE 专用转义(用 作转义符) $search = $mysqli->real_escape_string($_GET['q']); $search = str_replace(['%', '_'], ['%', '_'], $search); $sql = "SELECT * FROM posts WHERE title LIKE '%$search%' ESCAPE '\'";
-
ESCAPE ''必须显式声明,否则%还是被当成通配符 - 别用
addcslashes($str, '%_')—— 它不识别字符集,多字节下可能劈开 UTF-8 字节序列 - 如果用
mb_ereg_replace()或preg_replace('~[%_]~u', '\$0', $str),确保 PHP 启用了mbstring且正则带u修饰符
真正麻烦的地方不在函数本身,而在于:你得时刻清楚哪段是代码、哪段是数据,哪次是字符串、哪次是标识符。一不留神,转义就变成幻觉。










