一、addslashes()到底做了什么
addslashes()是PHP内置的字符串处理函数,它的作用很单一:在特定字符前加上反斜杠\进行转义。
受影响的字符有四个:
| 字符 | 转义后 |
|---|---|
单引号' |
\' |
双引号" |
\" |
反斜杠\ |
\\ |
| NUL字节 | \0 |
语法:
string addslashes ( string $str )
参数$str是必须传入的待转义字符串,函数返回转义后的新字符串。
这里有个容易忽略的点:addslashes()不会转义反斜杠本身以外的其他控制字符,也不会处理换行、回车等。它只针对上面列出的四个字符。
二、基础示例:观察转义效果
先看一个直接输出对比的例子。代码号学习编程建议在本地环境实际跑一遍,观察浏览器输出和查看源代码的区别。
<?php
$str = 'What does "WHO" mean?';
echo "原始字符串:" . $str;
echo "<br>";
echo "addslashes 之后:" . addslashes($str);
?>
输出:
原始字符串:What does "WHO" mean?
addslashes 之后:What does \"WHO\" mean?
双引号被加上了反斜杠。再看单引号的情况:
<?php
$str = "Who's the father of PHP?";
echo $str . " —— 直接用于数据库查询存在风险。<br>";
echo addslashes($str) . " —— 经过 addslashes 处理后。";
?>
输出:
Who's the father of PHP? —— 直接用于数据库查询存在风险。
Who\'s the father of PHP? —— 经过 addslashes 处理后。
单引号被转义为\',在旧式的字符串拼接SQL中,这样能避免引号提前闭合。
三、eval()场景下的转义需求
eval()会执行一段PHP代码字符串。如果字符串里含有单引号,直接拼接会导致语法错误。
<?php
$str = "Wow' PHP?";
eval("echo '" . addslashes($str) . "';");
?>
输出:
Wow' PHP?
这里addslashes()的作用是防止$str中的单引号破坏eval中字符串的边界。但说实话,现在PHP开发中eval()本身就应该尽量避免使用,它带来的安全风险远大于便利性。如果确实需要动态执行代码,优先考虑回调函数、策略模式等替代方案。
四、项目中的反思:为什么现在不推荐addslashes()做数据库转义
这是本文最想强调的部分。
很多老教程会告诉你:addslashes()可以让字符串"安全地"用于数据库查询。这个说法在十几年前或许成立,但现在来看是有问题的。
原因一:字符集问题
addslashes()不感知数据库连接的字符集。在GBK等多字节字符集中,某些字符的字节序列可能包含0x5C(反斜杠的ASCII码),addslashes()的转义反而可能被绕过,造成注入漏洞。
原因二:它只转义四个字符
SQL注入的payload不一定依赖单引号或双引号。数字型注入、注释符、UNION查询等场景,addslashes()无能为力。
原因三:预处理语句才是正解
PDO或MySQLi的预处理语句(PreparedStatements)将SQL结构与数据分离,数据库驱动层面处理转义,不依赖开发者手动拼接。这才是现在PHP项目应该采用的方式。
个人踩坑经历:早期做一个小型后台系统时,用addslashes()处理用户输入后拼接SQL,测试阶段没发现问题。上线后遇到一个用户昵称里包含特殊字符组合,配合GBK编码导致转义失效,差点造成数据泄露。从那以后,所有数据库操作一律走PDO预处理,再也没碰过addslashes()做SQL转义。
那addslashes()还有用吗?
有,但场景很窄。比如:
-
生成某些特定格式的文本文件,需要对引号做转义
-
旧系统维护,无法立即重构为预处理语句时的临时兼容
-
配合
stripslashes()做简单的字符串往返处理
五、addslashes()与相关函数的配合
stripslashes()是addslashes()的逆操作,去掉字符串中的反斜杠转义。
<?php
$original = "It's a \"test\" string.";
$escaped = addslashes($original);
echo "转义后:" . $escaped . "<br>";
echo "还原后:" . stripslashes($escaped);
?>
输出:
转义后:It\'s a \"test\" string.
还原后:It's a "test" string.
注意:stripslashes()并不是严格可逆的。如果原始字符串中本来就包含反斜杠,经过addslashes()再stripslashes()后,反斜杠的数量可能发生变化。这一点在处理文件路径时要特别小心。
addcslashes()则是更灵活的版本,可以指定要转义的字符范围:
<?php
$str = "Hello, PHP World!";
echo addcslashes($str, 'A..Z');
?>
输出:
\H\e\l\l\o, \P\H\P \W\o\r\l\d!
addcslashes()允许用字符范围指定转义目标,比addslashes()更可控,但也更容易误用。除非有明确需求,否则不建议在常规业务中随意使用。
六、本节课程知识要点
-
addslashes()转义四个字符:单引号、双引号、反斜杠、NUL字节。
-
它不感知字符集,在多字节编码环境下可能失效。
-
现在PHP数据库操作应使用PDO或MySQLi的预处理语句,而非addslashes()。
-
stripslashes()是逆操作,但对含反斜杠的原始字符串不可逆。
-
addcslashes()提供更灵活的转义范围控制,按需使用。
-
eval()场景下的转义只是历史用法,现在开发应避免eval()。
七、常见问题
Q:addslashes()和htmlspecialchars()有什么区别?
A:addslashes()用于字符串转义(如SQL拼接、eval),htmlspecialchars()用于HTML实体转义,防止XSS。两者用途不同,不能互相替代。
Q:用了addslashes()是不是就安全了?
A:不是。它只处理四个字符,且不感知字符集。安全防护需要根据具体场景选择正确的方案,数据库用预处理,HTML输出用htmlspecialchars(),URL用urlencode()。
Q:2026年还有必要学addslashes()吗?
A:有必要了解,因为维护旧项目时可能遇到。但新项目不应将其作为数据库转义手段。
addslashes()是一个简单直接的字符串转义函数,在PHP早期被广泛用于SQL拼接场景。随着预处理语句的普及和安全意识的提升,它的数据库转义角色已经退场。理解它的转义规则、局限性以及与现在方案的差异,有助于在维护旧代码和面试中做出准确判断。
写代码时,先问自己:这个转义是为了解决什么问题?数据库、HTML、URL还是文件路径?选对工具,比会用工具更重要。