PHP Conference Japan 2024

htmlentities

(PHP 4, PHP 5, PHP 7, PHP 8)

htmlentities將所有適用的字元轉換為 HTML 實體

描述

htmlentities(
    字串 $string,
    整數 $flags = ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401,
    ?字串 $encoding = null,
    布林值 $double_encode = true
): 字串

此函式在所有方面都與 htmlspecialchars() 相同,除了使用 htmlentities() 時,所有具有 HTML 字元實體對應項的字元都會被轉換成這些實體。get_html_translation_table() 函式可用於根據提供的 flags 常數傳回所使用的轉換表。

如果您想要解碼(反向),可以使用 html_entity_decode()

參數

string

輸入字串。

flags

下列旗標中的一個或多個的位元遮罩,指定如何處理引號、無效的程式碼單元序列以及所使用的文件類型。預設值為 ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401

可用的 flags 常數
常數名稱 描述
ENT_COMPAT 將轉換雙引號,並讓單引號保持不變。
ENT_QUOTES 將轉換雙引號和單引號。
ENT_NOQUOTES 將讓雙引號和單引號都不轉換。
ENT_IGNORE 靜默捨棄無效的程式碼單元序列,而不是傳回空字串。不建議使用此旗標,因為它» 可能會有安全隱患
ENT_SUBSTITUTE 以 Unicode 替換字元 U+FFFD (UTF-8) 或 &#FFFD; (否則) 取代無效的程式碼單元序列,而不是傳回空字串。
ENT_DISALLOWED 以 Unicode 替換字元 U+FFFD (UTF-8) 或 &#FFFD; (否則) 取代給定文件類型的無效程式碼點,而不是讓它們保持原狀。例如,這對於確保具有內嵌外部內容的 XML 文件格式正確可能很有用。
ENT_HTML401 將程式碼處理為 HTML 4.01。
ENT_XML1 將程式碼處理為 XML 1。
ENT_XHTML 將程式碼處理為 XHTML。
ENT_HTML5 將程式碼處理為 HTML 5。

encoding

一個可選參數,定義轉換字元時使用的編碼。

如果省略,encoding 預設為 default_charset 組態選項的值。

雖然這個參數在技術上是可選的,但如果 default_charset 組態選項對於給定的輸入可能設定不正確,強烈建議您為程式碼指定正確的值。

支援下列字元集

支援的字元集
字元集 別名 描述
ISO-8859-1 ISO8859-1 西歐,拉丁文-1。
ISO-8859-5 ISO8859-5 很少使用的西里爾字元集(拉丁文/西里爾文)。
ISO-8859-15 ISO8859-15 西歐,拉丁文-9。新增了歐元符號,以及拉丁文-1 (ISO-8859-1) 中缺少的法文和芬蘭文字母。
UTF-8   與 ASCII 相容的多位元組 8 位元 Unicode。
cp866 ibm866, 866 特定於 DOS 的西里爾字元集。
cp1251 Windows-1251, win-1251, 1251 特定於 Windows 的西里爾字元集。
cp1252 Windows-1252, 1252 特定於 Windows 的西歐字元集。
KOI8-R koi8-ru, koi8r 俄文。
BIG5 950 繁體中文,主要在台灣使用。
GB2312 936 簡體中文,國家標準字元集。
BIG5-HKSCS   具有香港擴充功能的 Big5,繁體中文。
Shift_JIS SJIS, SJIS-win, cp932, 932 日文
EUC-JP EUCJP, eucJP-win 日文
MacRoman   Mac OS 使用的字元集。
''   空字串會依照指令碼編碼 (Zend multibyte)、default_charset 和目前地區設定 (請參閱 nl_langinfo()setlocale()) 的順序啟用偵測。不建議使用。

注意 不會辨識任何其他字元集。將會改為使用預設編碼,並發出警告。

double_encode

double_encode 關閉時,PHP 不會編碼現有的 html 實體。預設為轉換所有內容。

傳回值

傳回編碼後的字串。

如果輸入的 string 在給定的 encoding 中包含無效的程式碼單元序列,則會傳回空字串,除非設定了 ENT_IGNOREENT_SUBSTITUTE 旗標。

變更記錄

版本 描述
8.1.0 flagsENT_COMPAT 變更為 ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401
8.0.0 encoding 現在可為 null。

範例

範例 1:htmlentities() 範例

<?php
$str
= "一個 '引號' 是 <b>粗體</b>";

echo
htmlentities($str);
echo
"\n\n";
echo
htmlentities($str, ENT_COMPAT);
?>

上面的範例會輸出

A &#039;quote&#039; is &lt;b&gt;bold&lt;/b&gt;

A 'quote' is &lt;b&gt;bold&lt;/b&gt

範例 2:使用 ENT_IGNORE

<?php
$str
= "\x8F!!!";

// 輸出一個空字串
echo htmlentities($str, ENT_QUOTES, "UTF-8");

// 輸出 "!!!"
echo htmlentities($str, ENT_QUOTES | ENT_IGNORE, "UTF-8");
?>

參見

新增註解

使用者貢獻的註解 22 則註解

Sijmen Ruwhof
14 年前
以下是一個關於使用此函式來保護您的應用程式免於跨網站指令碼 (XSS) 漏洞的重要說明。

當在 HTML 標籤的屬性中印出使用者輸入時,如果使用單引號來定義標籤屬性值的邊界,`htmlentities()` 的預設設定並不能保護您免受 XSS 攻擊。此時,透過注入單引號就有可能產生 XSS 攻擊。

<?php
$_GET
['a'] = "#000' onload='alert(document.cookie)";
?>

可能產生 XSS 攻擊 (不安全)

<?php
$href
= htmlEntities($_GET['a']);
print
"<body bgcolor='$href'>"; # 結果: <body bgcolor='#000' onload='alert(document.cookie)'>
?>

使用 'ENT_QUOTES' 引號樣式選項,以確保不會發生 XSS 攻擊,且您的應用程式是安全的。

<?php
$href
= htmlEntities($_GET['a'], ENT_QUOTES);
print
"<body bgcolor='$href'>"; # 結果: <body bgcolor='#000&#039; onload=&#039;alert(document.cookie)'>
?>

'ENT_QUOTES' 選項並不能保護您免於在某些標籤的屬性中執行 JavaScript,例如 'a' 標籤的 'href' 屬性。當點擊以下連結時,所提供的 JavaScript 將會被執行。

<?php
$_GET
['a'] = 'javascript:alert(document.cookie)';
$href = htmlEntities($_GET['a'], ENT_QUOTES);
print
"<a href='$href'>連結</a>"; # 結果: <a href='javascript:alert(document.cookie)'>連結</a>
?>
j2teamnnl at gmail dot com
2 年前
以上的答案對於多種語言(如法語)來說並不正確。
我已更正它
function xml_entities($strIn)
{
if (is_numeric($strIn)) {
return $strIn;
}
$strOut = null;

$arrStr = mb_str_split($strIn);
foreach ($arrStr as $char) {
$ord = mb_ord($char);

if (($ord > 0 && $ord < 32) || ($ord >= 127)) {
$strOut .= "&amp;#{$ord};";
}
else {
switch ($char) {
case '<'
$strOut .= '&lt;';
break;
case '>'
$strOut .= '&gt;';
break;
case '&'
$strOut .= '&amp;';
break;
case '"'
$strOut .= '&quot;';
break;
default
$strOut .= $char;
}
}
}

return $strOut;
}
q (dot) rendeiro (at) gmail (dot) com
17 年前
我看過很多轉換所有實體的函式,但我需要在資料庫欄位中進行全文搜尋,該欄位具有具名實體而不是數值實體(由 tinymce 編輯),所以我搜尋了 tinymce 原始碼,並找到一個具有值到實體對應的字串。因此,我寫了以下函式來使用具名實體編碼使用者的查詢。

我使用的字串與原始字串不同,因為我不想轉換 ' 或 "。字串太長了,所以我必須剪切它。要取得原始字串,請檢查 TinyMCE 原始碼並搜尋 nbsp 或其他實體 ;)

<?php

$entities_unmatched
= explode(',', '160,nbsp,161,iexcl,162,cent, [...] ');
$even = 1;
foreach(
$entities_unmatched as $c) {
if(
$even) {
$ord = $c;
} else {
$entities_table[$ord] = $c;
}
$even = 1 - $even;
}

function
encode_named_entities($str) {
global
$entities_table;

$encoded_str = '';
for(
$i = 0; $i < strlen($str); $i++) {
$ent = @$entities_table[ord($str{$i})];
if(
$ent) {
$encoded_str .= "&$ent;";
} else {
$encoded_str .= $str{$i};
}
}
return
$encoded_str;
}

?>
2962051004 at qq dot com
6 年前
<?php

/**
* 將中文轉換為 Html 實體
* Convert Chinese in HTML to entity
* Author QiangGe
* Mail 2962051004@qq.com
*
*/

$str = <<<EOT
你好 world
EOT;

function
ChineseToEntity($str) {
return
preg_replace_callback(
'/[\x{4e00}-\x{9fa5}]/u', // utf-8
// '/[\x7f-\xff]+/', // 如果是 gb2312
function ($matches) {
$json = json_encode(array($matches[0]));
preg_match('/\[\"(.*)\"\]/', $json, $arr);
/*
* 透過 json_encode 函式將中文轉換為 unicode
* 然後用正規表達式取出 unicode
* Turn the Chinese into Unicode through the json_encode function, then extract Unicode from regular.
* 我認為這個想法很完美。
*/
return '&#x'. str_replace('\\u', '', $arr[1]). ';';
},
$str
);
}

echo
ChineseToEntity($str);
// &#x4f60;&#x597d; world
phil at lavin dot me dot uk
14 年前
以下將使字串對 XML 完全安全。

<?php
function philsXMLClean($strin) {
$strout = null;

for (
$i = 0; $i < strlen($strin); $i++) {
$ord = ord($strin[$i]);

if ((
$ord > 0 && $ord < 32) || ($ord >= 127)) {
$strout .= "&amp;#{$ord};";
}
else {
switch (
$strin[$i]) {
case
'<':
$strout .= '&lt;';
break;
case
'>':
$strout .= '&gt;';
break;
case
'&':
$strout .= '&amp;';
break;
case
'"':
$strout .= '&quot;';
break;
default:
$strout .= $strin[$i];
}
}
}

return
$strout;
}
?>
hajo-p
10 年前
`ENT_HTML5` 旗標也會使用 `htmlentities` 移除換行符號(如 \n),而 `htmlspecialchars` 不受影響。

如果您之後想在該字串上使用 nl2br,您可能會像我一樣最終尋找問題。這不適用於其他旗標,例如 `ENT_XHTML`,這讓我感到困惑。

已在 PHP 5.4 / 5.5 / 5.6-dev 中進行測試,結果相同,因此這似乎是預期的「功能」。
realcj at g mail dt com
18 年前
如果您正在為 Flash 建立 loadvars 頁面,並且遇到特殊字元的問題,例如 " & "、" ' " 等,您應該將它們跳脫,以供 Flash 使用。

在 Flash 的 ActionScript 中嘗試使用 trace(escape("&")); 來查看 & 的跳脫碼。

% = %25
& = %26
' = %27

<?php
function flashentities($string){
return
str_replace(array("&","'"),array("%26","%27"),$string);
}
?>

這兩個是我比較關心的。您可能會有不同的狀況。
ustimenko dot alexander at gmail dot com
12 年前
對於那些希望在 htmlentities 後恢復其國家字母的西班牙人(及其他國家的人)來說:)

<?php
protected function _decodeAccented($encodedValue, $options = array()) {
$options += array(
'quote' => ENT_NOQUOTES,
'encoding' => 'UTF-8',
);
return
preg_replace_callback(
'/&\w(acute|uml|tilde);/',
create_function(
'$m',
'return html_entity_decode($m[0], ' . $options['quote'] . ', "' .
$options['encoding'] . '");'
),
$encodedValue
);
}
?>
wd at NOSPAMwd dot it
12 年前
嗨,大家好,

經過多次測試,我發現以下幾點:

- 當您指定標誌和字元集時,htmlentities() 函數會移除 "à"、"è" 等字元。

- 當您沒有指定任何內容時,htmlentities() 函數 *不會* 移除上述字元。

因此,讓我們假設:

<?php

$str
= "Hèèèllooo";

$res_1 = htmlentities($str, ENT_QUOTES, "UTF-8");
$res_2 = htmlentities($str);

echo
var_dump($res_1); // 結果:string '' (length=0)
echo var_dump($res_2); // string 'H&egrave;&egrave;&egrave;llooo' (length=30)

?>

我將此用於評論的 textarea 內容。無論如何,請注意,使用 "$res_2" 形式的函數將會保留未轉換的單引號/雙引號。此時您應該使用 str_replace() 函數來處理這些字元,但請小心,因為:

<?php

$str
= "'Hèèèllooo'";

$res_2 = str_replace("'","&#039;",$str);
$res_2 = htmlentities($str);
echo
var_dump($res_2); // string '&amp;#039;H&egrave;&egrave;&egrave;llooo&amp;#039;'

$res_3 = htmlentities($str);
$res_3 = str_replace("'","&#039;",$res_3);
echo
var_dump($res_3); // string '&#039;H&egrave;&egrave;&egrave;llooo&#039;' --> 很好
?>

希望這對您有所幫助。

祝好,
W.D.
n at erui dot eu
12 年前
html entities 不會編碼所有 Unicode 字元。它會編碼它能編碼的字元 [所有 Latin-1 字元],而其他字元則會溜走。 &#1033; 是我使用的討厭字元。我一直在尋找一個可以編碼所有內容的函數,但最終我寫了這個。這是我能讓它變得最簡單的方式。請查閱 ASCII 表格,以自訂包含/省略您想要/不想要的字元。我敢肯定它不快。

// Unicode 安全的 htmlentities。
// 將「普通」字元作為字元返回,並將怪異字元作為數值 HTML 實體返回。
function superentities( $str ){
// 擺脫現有的實體,否則會雙重跳脫
$str = html_entity_decode(stripslashes($str),ENT_QUOTES,'UTF-8');
$ar = preg_split('/(?<!^)(?!$)/u', $str ); // 返回每個多位元組字元的陣列
foreach ($ar as $c){
$o = ord($c);
if ( (strlen($c) > 1) || /* 多位元組 [unicode] */
($o <32 || $o > 126) || /* <- 控制/拉丁怪異字元 -> */
($o >33 && $o < 40) ||/* 引號 + & 符號 */
($o >59 && $o < 63) /* html */
) {
// 轉換為數值實體
$c = mb_encode_numericentity($c,array (0x0, 0xffff, 0, 0xffff), 'UTF-8');
}
$str2 .= $c;
}
return $str2;
}
Bassie (:
21 年前
請注意,在任何其他將編輯文字的函數(如 nl2br())之前,您必須先使用 htmlentities()。

如果您先使用 nl2br(),htmlentities() 函數會將 < br > 變更為 &lt;br&gt;。
robin at robinwinslow dot co dot uk
13 年前
htmlentities 似乎在 5.1.6 版和 5.3.3 版之間的某個時間點發生了變更,現在對於任何包含英鎊符號的字串,它都會傳回空字串。

$ php -v
PHP 5.1.6 (cli) (built: May 22 2008 09:08:44)
$ php -r "echo htmlentities('£hello', null, 'utf-8');"
&pound;hello
$

$ php -v
PHP 5.3.3 (cli) (built: Aug 19 2010 12:07:49)
$ php -r "echo htmlentities('£hello', null, 'utf-8');"
$

(第二次會傳回空字串)

只是提醒您一下。
Waygood
13 年前
當將值放入註解標籤 <!-- --> 內時,您也應該將 -- 替換為 &#45;&#45;,因為這會結束您的標籤並顯示註解的其餘部分。
admin at wapforum dot rs
13 年前
一個有用的小函數,用於轉換不同輸入中的符號。
<?php
function ConvertSimbols($var, $ConvertQuotes = 0) {
if (
$ConvertQuotes > 0) {
$var = htmlentities($var, ENT_NOQUOTES, 'UTF-8');
$var = str_replace('\"', '', $var);
$var = str_replace("\'", '', $var);
} else {
$var = htmlentities($var, ENT_QUOTES, 'UTF-8');
}
return
$var;
}
?>

使用引號的範例訊息用法

$message = ConvertSimbols($message);

不使用引號的範例連結用法

$link = ConvertSimbols($link, 1);
Jeff
6 年前
使用 AJAX 呼叫 PHP 寫入 XML 時,有一個很少被提及的功能。我使用 htmlentities() 掙扎了好幾個小時,因為寫入 XML 文件中的內容與預期的不符。我自然而然地認為,在將字串寫入 XML 之前,我應該先轉換字串,以遵守 XML 對於非法字元的規則。令我驚訝的是,當使用 htmlentities() 或 htmlspecialchars() 進行轉換,然後寫入 XML 檔案時,產生的 & 符號會被事後轉換!請考慮以下範例:

<?php
$str
= "<b>我很酷</b>" ;
$str = htmlentities($str) ;
?>

當您將 $str 附加到 XML 元素並儲存() 檔案時,您會預期 XML 文件的原始碼看起來像這樣:

<ele>&lt;b&gt;我很酷&lt;/b&gt;</ele>

但這不是實際發生的情況。產生的 & 符號會被 PHP 自動轉換為 &amp;,而您的原始碼最終看起來會像這樣:

<ele>&amp;lt;b&amp;gt;我很酷&amp;lt;/b&amp;gt;</ele>

如您所見,當嘗試將 XML 資料輸出回 HTML 時,這會產生問題。請務必記住,以這種方式寫入 XML 時,像是 ">" 和 "<" 等特殊字元;PHP 會自動轉換它們,因此在某些情況下不需要使用 htmlentities()。我認為這個功能是為了協助透過標頭查詢傳遞資料,以避免保留字元與標頭查詢中的其他字元衝突(例如 & 或 =)。現在我了解到,舊版本的 PHP 可能不是這樣,這可能是我使用的版本(PHP 版本 5.6.32)的功能。我認為對於舊版本,如先前筆記所述,必須使用 htmlentities() 或 htmlspecialchars()。此外,我在我的 HTML 和 XML 中都使用 UTF-8 字元集,我不確定這是否也會影響我得到的結果。

無論如何,我花費了許多小時在使用 htmlentities() 轉換字串以進行 XML 寫入和儲存時掙扎,而我所需要做的只是不要使用該函數,讓 PHP 為我轉換字串。我希望這對您有所幫助,因為我想我不是唯一一個在這方面遇到困難的人。
Tom Walter
16 年前
請注意,從 5.2.5 版本開始,如果輸入字串包含您指定的輸出編碼無效的字元,則此函數會傳回 null。

您可能會認為它只會移除無效字元,但它不會這樣做。

您可以像這樣自行移除字元

iconv('utf-8','utf-8',$str);

您也可以將其與 htmlentities 結合使用

$str = htmlentities(iconv('UTF-8', 'UTF-8//IGNORE', $str, ENT_QUOTES, 'UTF-8');

應該會得到一個使用 htmlentities 編碼為 utf-8 的字串,並且任何不受支援的字元都將被移除。
jake_mcmahon at hotmail dot com
20 年前
此函數對於防禦 XSS(跨網站指令碼攻擊)特別有用。XSS 會利用程式碼中的漏洞,無論是在 Javascript 或 PHP 中。XSS 通常(如果不是總是)使用 HTML 實體來進行惡意行為,因此此函數與您的腳本(特別是搜尋或提交腳本)合作,是打擊「H4X0rz」的非常有用工具。
steve at mcdragonsoftware dot com
13 年前
我很高興 5.4 版本有 XML 支援,但是我們許多人都在使用較舊的安裝版本,有些人甚至仍然必須使用 PHP4。如果您和我一樣,您會因為嘗試將 htmlentites/htmlspecial chars 用於 XML 輸出而感到沮喪。我原本希望找到一個強制使用數字編碼的選項,但找不到,因此我編寫了自己的 xmlencode 函數,現在我將其提供出來

用法

$string xmlencode( $string )

它會將 htmlspecialchars 用於有效的 XML 實體 amp、quote、lt、gt、(apos),並傳回所有其他非字母數字字元的數字實體。

-------------------------------------------

<?php
if( !function_exists( 'xmlentities' ) ) {
function
xmlentities( $string ) {
$not_in_list = "A-Z0-9a-z\s_-";
return
preg_replace_callback( "/[^{$not_in_list}]/" , 'get_xml_entity_at_index_0' , $string );
}
function
get_xml_entity_at_index_0( $CHAR ) {
if( !
is_string( $CHAR[0] ) || ( strlen( $CHAR[0] ) > 1 ) ) {
die(
"function: 'get_xml_entity_at_index_0' requires data type: 'char' (single character). '{$CHAR[0]}' does not match this type." );
}
switch(
$CHAR[0] ) {
case
"'": case '"': case '&': case '<': case '>':
return
htmlspecialchars( $CHAR[0], ENT_QUOTES ); break;
default:
return
numeric_entity_4_char($CHAR[0]); break;
}
}
function
numeric_entity_4_char( $char ) {
return
"&#".str_pad(ord($char), 3, '0', STR_PAD_LEFT).";";
}
}
?>
h_guillaume at hotmail dot com
14 年前
我使用此函數對所有 XML 實體以及所有 XML 中未定義的 &something; 進行編碼,例如 &trade;。
您也可以使用我的解碼函數來解碼您編碼的內容。
我的函數有點像 htmlentities。
如果您想將其他字串排除在編碼之外,您也可以將它們新增到陣列中。

<?php
function xml_entity_decode($text, $charset = 'Windows-1252'){
// 雙重解碼,因此如果值是 &amp;trade;,它會變成 Trademark
$text = html_entity_decode($text, ENT_COMPAT, $charset);
$text = html_entity_decode($text, ENT_COMPAT, $charset);
return
$text;
}

function
xml_entities($text, $charset = 'Windows-1252'){
// 除錯和測試
// $text = "test &amp; &trade; &amp;trade; abc &reg; &amp;reg; &#45;";

// 首先,我們對 HTML 字元進行編碼,這些字元在 XML 中也是無效的
$text = htmlentities($text, ENT_COMPAT, $charset, false);

// 來自 Wiki 的 XML 字元實體陣列
// 注意: &apos; 在 UTF-8 或 UTF-16 中沒有用處
$arr_xml_special_char = array("&quot;","&amp;","&apos;","&lt;","&gt;");

// 建立正規表示式字串,以排除所有包含 XML 特殊字元的字串
$arr_xml_special_char_regex = "(?";
foreach(
$arr_xml_special_char as $key => $value){
$arr_xml_special_char_regex .= "(?!$value)";
}
$arr_xml_special_char_regex .= ")";

// 掃描陣列以尋找 &something_not_xml; 語法
$pattern = "/$arr_xml_special_char_regex&([a-zA-Z0-9]+;)/";

// 將 &something_not_xml; 替換為 &amp;something_not_xml;
$replacement = '&amp;${1}';
return
preg_replace($pattern, $replacement, $text);
}
?>
za at byza dot it
16 年前
使用不同字元集的文件時遇到問題?

htmlentities 和 html_entity_decode 可用於在字元集之間轉換!

範例函數

<?php
function utf2latin($text) {
$text=htmlentities($text,ENT_COMPAT,'UTF-8');
return
html_entity_decode($text,ENT_COMPAT,'ISO-8859-1');
}
?>
chris at ocproducts dot com
7 年前
即使設定了 ENT_SUBSTITUTE,此函數也會在錯誤的輸入上拋出警告,因此請做好準備。
drallen at cs dot uwaterloo dot ca
14 年前
如果您的目的是將字元集中*所有*字元轉換為其對應的 HTML 實體,而不僅僅是具名的字元,請參考 https://php.dev.org.tw/manual/en/function.mb-convert-encoding.php。非具名字元將會被 HTML 數字編碼取代。例如

$text = mb_convert_encoding($text, 'HTML-ENTITIES', "UTF-8");
To Top