← PHP htmlspecialchars()函数:特殊字符转HTML实体教程 PHP implode()函数:数组元素连接成字符串教程 →

PHP htmlspecialchars_decode()函数:HTML实体还原字符教程

著
原创 2026-10-10 PHP 已有人查阅

一、函数定位与核心作用

htmlspecialchars_decode()是PHP内置的字符串函数,把预定义的HTML实体还原成对应字符。它是htmlspecialchars()的逆操作:一个把字符转成实体,一个把实体还原成字符。

它处理的实体范围与htmlspecialchars()严格对应,只有五个:

HTML实体 还原后字符 说明
& & 和号
" " 双引号
' ' 单引号
&lt; < 小于号
&gt; > 大于号

注意范围边界:&copy;、&nbsp;这类命名实体,以及&#20013;这类数字实体,htmlspecialchars_decode()不处理。需要更广的解码范围,得用html_entity_decode()。

函数签名:

htmlspecialchars_decode(string $string, int $flags = ENT_COMPAT | ENT_HTML401): string

两个参数,只有$string必填。返回值是解码后的字符串。

二、参数逐项拆解

string(必填)

待解码的字符串,里面包含一个或多个预定义HTML实体。

flags(可选)

控制引号处理方式和文档类型。引号相关常量:

  • ENT_COMPAT:默认值,只解码双引号实体&quot;,保留单引号实体&#039;。

  • ENT_QUOTES:同时解码双引号和单引号实体。

  • ENT_NOQUOTES:两者都不解码。

文档类型相关常量:

  • ENT_HTML401:默认值,按HTML4.01处理。

  • ENT_XML1:按XML1.0处理。

  • ENT_XHTML:按XHTML处理。

  • ENT_HTML5:按HTML5处理。

这四个文档类型常量从PHP5.4.0开始加入。此前版本只有引号相关的flags可用。

三、代码号学习编程示例

先看基础解码:

<?php
$str = "&lt;i&gt;代码号学习编程&lt;/i&gt;";
echo htmlspecialchars_decode($str);
?>

输出:

<i>代码号学习编程</i>

实体还原后,如果直接输出到页面,浏览器会把它当成真正的<i>标签解析,文字呈现斜体。这正是解码后需要谨慎处理的原因。

再看引号处理差异:

<?php
$str = "&quot;代码号&quot; and &#039;学习编程&#039;";

echo htmlspecialchars_decode($str);
echo "<br>";
echo htmlspecialchars_decode($str, ENT_QUOTES);
echo "<br>";
echo htmlspecialchars_decode($str, ENT_NOQUOTES);
?>

输出:

"代码号" and &#039;学习编程&#039;
"代码号" and '学习编程'
&quot;代码号&quot; and &#039;学习编程&#039;

ENT_COMPAT只还原双引号,单引号实体保留;ENT_QUOTES两者都还原;ENT_NOQUOTES两者都不动。三种模式下&lt;、&gt;、&amp;都会被还原,因为它们不受引号flags控制。

解码范围边界示例:

<?php
$str = "&copy; 2026 &amp; &#20013;&#25991;";
echo htmlspecialchars_decode($str, ENT_QUOTES);
?>

输出:

&copy; 2026 & &#20013;&#25991;

&amp;被还原成&,但&copy;和数字实体&#20013;原样保留。这是因为htmlspecialchars_decode()只认那五个预定义实体。要处理全部实体,得换成html_entity_decode($str,ENT_QUOTES,'UTF-8')。

四、与htmlspecialchars()的互逆关系

两者方向相反,字符集固定:

  • htmlspecialchars():&→&amp;,"→&quot;,'→&#039;,<→&lt;,>→&gt;

  • htmlspecialchars_decode():上述实体还原回原字符

往返转换可以验证一致性:

<?php
$original = "代码号 <b>学习编程</b> & ''";
$encoded = htmlspecialchars($original, ENT_QUOTES, "UTF-8");
$decoded = htmlspecialchars_decode($encoded, ENT_QUOTES);

var_dump($original === $decoded);
?>

输出:

bool(true)

只要flags一致,往返后能得到原始字符串。这一点在数据校验和调试时很有用。

五、项目反思与踩坑经历

踩坑一:解码后直接输出,XSS防护被绕过

后台做评论内容预览,为了让管理员看到用户提交的原始格式,直接htmlspecialchars_decode()后输出。用户提交的&lt;script&gt;还原成<script>标签,页面执行了脚本。解码后的内容必须重新按不可信数据处理,输出前再次转义。预览场景更稳妥的做法是保留实体显示,或使用沙箱渲染。

踩坑二:指望它解码所有实体

处理一份含&nbsp;和&copy;的采集数据,用htmlspecialchars_decode()后发现这些实体纹丝不动。原因是函数只认五个预定义实体。换成html_entity_decode($str,ENT_QUOTES,'UTF-8')才处理干净。选函数前先确认数据里的实体类型。

踩坑三:编码不一致导致引号还原异常

某次处理GBK页面的数据,&#039;没有被还原成单引号。检查发现flags用了默认的ENT_COMPAT,单引号实体本就不在解码范围内。改成ENT_QUOTES后正常。单引号实体是否还原,取决于flags,不是编码问题。

踩坑四:重复解码破坏数据

数据在入库前已经用htmlspecialchars()转义,展示时又调htmlspecialchars_decode(),再叠加一层输出转义,逻辑绕了三层,结果页面显示忽而实体忽而字符。理顺分层后:入库存原始数据,输出统一转义,中间不做多余解码。

个人建议

  • 解码仅用于数据处理、比对、截取等中间环节,输出环节谨慎使用。

  • 从外部来的实体字符串,解码后按不可信内容处理。

  • 需要解码范围更广时选html_entity_decode(),别指望htmlspecialchars_decode()覆盖所有实体。

  • flags保持一致,避免htmlspecialchars()用ENT_QUOTES转义、解码时用ENT_COMPAT导致单引号实体残留。

六、本节课程知识要点

  • htmlspecialchars_decode()把五个预定义HTML实体还原成字符,是htmlspecialchars()的逆操作。

  • 两个参数:字符串、flags,仅字符串必填。

  • ENT_COMPAT解双引号实体,ENT_QUOTES解双引号和单引号实体,ENT_NOQUOTES都不解。

  • 只处理&amp;、&quot;、&#039;、&lt;、&gt;,不处理&copy;、&nbsp;等命名实体和数字实体。

  • 需要更广解码范围用html_entity_decode()。

  • 文档类型常量ENT_HTML401、ENT_HTML5、ENT_XHTML、ENT_XML1从PHP5.4.0起可用。

  • 解码后内容视同不可信,输出前需重新转义。

七、扩展应用场景

场景一:数据比对与搜索

数据库里存的是实体化文本,用户搜索原始字符。搜索前对两边统一做htmlspecialchars_decode(),能提高匹配准确度。

场景二:内容摘要截取

带实体字符的文本按字节截取,容易把&amp;切成&am这样的残片。先解码再截取,再按需重新转义,摘要更整齐。

场景三:迁移旧数据

老系统把用户内容实体化存库,迁移时需要还原。对指定字段统一调用htmlspecialchars_decode(),再按新规则重新处理入库。

场景四:调试输出

排查页面显示问题时,用htmlspecialchars_decode()看清数据原本内容,判断是转义层数不对还是编码问题。

htmlspecialchars_decode()处理的是固定五个实体的还原,范围窄但对应关系清晰。它和htmlspecialchars()互为逆操作,配合使用能验证转义逻辑。项目里容易踩的坑集中在两点:一是把它当万能解码器,指望处理所有实体;二是解码后直接输出,绕过了XSS防护。明确它的处理边界,把解码放在数据处理环节而非输出环节,用起来就稳。需要覆盖命名实体和数字实体时,换html_entity_decode()。

← PHP htmlspecialchars()函数:特殊字符转HTML实体教程 PHP implode()函数:数组元素连接成字符串教程 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号