PHP输出转义需按目标环境选择函数:浏览器用htmlspecialchars($str, ENT_QUOTES, 'UTF-8'),JS上下文用json_encode(),数据库用预处理;混淆入库与输出转义会导致乱码或XSS。

PHP 输出转义不是“学个函数就完事”,而是要分清楚:你输出到哪儿?浏览器?JS上下文?数据库?URL?目标不同,该用的函数、参数、甚至顺序都完全不同。用错一个,轻则显示乱码,重则 XSS 漏洞。
htmlspecialchars() 为什么必须加 ENT_QUOTES 和 charset 参数
很多人只写 htmlspecialchars($str),结果在含单引号的属性值里翻车。比如:<button data-label="O'Reilly"> —— 不加 ENT_QUOTES,单引号不转义,HTML 解析器会把 O' 当成属性结束,后面全乱。
-
ENT_QUOTES确保单双引号都被转成'和",这是 HTML 属性安全的底线 - 第三个参数(字符集)必须显式传,比如
'UTF-8';不传时 PHP 会按默认编码处理,老版本默认是 ISO-8859-1,中文变 - 别用
htmlentities()替代 —— 它会把所有非 ASCII 字符(如中文、emoji)也转成实体,没必要且影响可读性
echo 里混 JS 代码时,htmlspecialchars() 不够用
直接把 PHP 变量塞进 <script> 标签,即使用了 htmlspecialchars(),依然可能被 JS 引擎执行。例如:echo "<script>alert({$user_input});</script>" —— $user_input 是 1); drop table users; //,htmlspecialchars() 只防 HTML,不防 JS 注入。
- 正确做法:先用
json_encode($value, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG)把值转成 JS 安全字符串,再放进<script> - 不要手动拼
"或'包裹 ——json_encode()自动处理引号、换行、控制字符 - 如果必须输出纯 JS 片段(非变量),用
addslashes()+ 手动包裹引号反而更危险;优先走json_encode()+document.write()或 DOM 操作
数据库写入和页面输出是两件事,不能套同一个转义
有人把 addslashes() 的结果直接 echo 到页面,结果看到一堆 \' —— 这是典型混淆了「入库转义」和「输出转义」。
立即学习“PHP免费学习笔记(深入)”;
-
addslashes()/mysqli_real_escape_string()只用于拼 SQL 查询,且仅限旧式拼接(现代应优先用预处理) - 从数据库读出的数据,是原始未转义内容,输出前必须重新做
htmlspecialchars(),而不是“再解一次” - 如果数据库字段存的是 HTML(比如富文本),且你信任其来源,输出时用
htmlspecialchars()就会把<p>变成字面量;此时应校验+白名单过滤(如使用strip_tags()+ 允许的标签),而非盲目转义
最常被忽略的一点:转义必须紧贴输出动作。中间经过缓存、日志、JSON 编码、模板引擎等环节时,很容易被重复转义或漏转义。建议所有输出变量统一走封装函数,比如 html($str) 内部固定调用 htmlspecialchars($str, ENT_QUOTES, 'UTF-8'),并禁止在其他地方裸用 echo。



















