PHP 提供兩個 HTML 實體編碼函數:htmlspecialchars() 與 htmlentities()。兩者皆用於防止 XSS 攻擊、將特殊字元轉為 HTML 實體,但處理範圍與中文支援度截然不同。本文詳細比較並提供最佳實務。
| 特性 | htmlspecialchars() | htmlentities() |
|---|---|---|
| 轉換範圍 | 僅 5 個特殊字元:& " ' < > | 所有可轉換為 HTML 實體的字元(含拉丁文、希臘文、中文等) |
| 中文處理 | 不動中文,直接保留 | 若未指定編碼,會將中文轉為實體(導致亂碼) |
| 效能 | 較快 | 較慢(掃描範圍大) |
| 常用旗標 | ENT_COMPAT / ENT_QUOTES / ENT_NOQUOTES | 同左 |
<?php
$str = "John & 'Adams'";
// ENT_COMPAT:預設,僅轉雙引號
echo htmlspecialchars($str, ENT_COMPAT); // John & 'Adams'
// ENT_QUOTES:雙引號與單引號皆轉
echo htmlspecialchars($str, ENT_QUOTES); // John & 'Adams'
// ENT_NOQUOTES:引號皆不轉
echo htmlspecialchars($str, ENT_NOQUOTES); // John & 'Adams'
?>
轉換對照:& → &、" → "、' → '(ENT_QUOTES)、< → <、> → >。
<?php
$str = "測試頁面";
// 未指定編碼:預設 ISO-8859-1,中文會變亂碼實體
echo htmlentities($str);
// 輸出:²âÊÔÒ³Ãæ
// 指定編碼:正確處理中文
echo htmlentities($str, ENT_COMPAT, "UTF-8");
// 或 GB2312/Big5
echo htmlentities($str, ENT_COMPAT, "GB2312");
// 輸出:測試頁面(中文保持可讀,特殊符號實體化)
?>
<?php
$str = '測試頁面 & "quotes"';
echo "htmlentities (UTF-8):\n";
echo htmlentities($str, ENT_QUOTES, "UTF-8") . "\n\n";
echo "htmlspecialchars:\n";
echo htmlspecialchars($str, ENT_QUOTES, "UTF-8") . "\n";
/*
htmlentities (UTF-8):
測試頁面 <script>alert(1)</script> & "quotes"
htmlspecialchars:
測試頁面 <script>alert(1)</script> & "quotes"
*/
?>
ENT_COMPAT(預設):轉換雙引號,不轉單引號ENT_QUOTES:雙引號與單引號皆轉換 (推薦)ENT_NOQUOTES:引號皆不轉換ENT_HTML401 / ENT_HTML5 / ENT_XML1 / ENT_XHTML:指定文件型別(PHP 5.4+)htmlspecialchars($str, ENT_QUOTES, 'UTF-8'),效能佳且不動中文。htmlentities($str, ENT_QUOTES, 'UTF-8'),並確保編碼參數正確。ENT_HTML5 或手動 html_entity_decode() 後再編碼。<?php
function h($str, $flags = ENT_QUOTES, $encoding = 'UTF-8') {
return htmlspecialchars($str, $flags, $encoding);
}
function he($str, $flags = ENT_QUOTES, $encoding = 'UTF-8') {
return htmlentities($str, $flags, $encoding);
}
// 使用:echo h($userInput);
?>