# UTF-8:字符編碼的秘密
[http://htmlpurifier.org/docs/enduser-utf8.html#findcharset](http://htmlpurifier.org/docs/enduser-utf8.html#findcharset)
## 尋找真實的編碼
最初是ASCII,事情很簡單。但是它們不好,因為沒有人能用西里爾文或泰文寫作。因此,爆炸了字符編碼,以擴展ASCII可以表示的字符來解決該問題。字符編碼歷史的這個荒謬的簡化版本向我們表明,現在有許多字符編碼在浮動。
> 一個**字符編碼**告訴計算機如何解釋原始零和一成真實人物。通常通過將數字與字符配對來實現。
>
> 周圍有許多不同類型的字符編碼,但是我們最常處理的是ASCII,8位編碼和基于Unicode的編碼。
>
> * **ASCII**是基于英文字母的7位編碼。
> * **8位編碼**是ASCII的擴展,增加了有用的非標準字符(例如é和?)的雜燴。他們只能添加127個字符,因此通常一次僅支持一個腳本。當您在網絡上看到某個頁面時,很可能會以其中一種編碼方式對其進行編碼。
> * **基于Unicode的編碼**實現Unicode標準,包括UTF-8,UTF-16和UTF-32 / UCS-4。它們超越了8位,并且支持世界上幾乎所有語言。作為網絡的主要國際編碼方式,UTF-8受到越來越多的關注。
我們旅程的第一步是找出您網站的編碼。最可靠的方法是詢問您的瀏覽器:
火狐瀏覽器
工具>頁面信息:編碼
IE瀏覽器
查看>編碼:項目符號為非官方名稱
Internet Explorer不會為您提供字符編碼的MIME名稱(即有用/真實),因此您必須使用其描述來查找它。一些常見的:
| IE的描述 | Mime Name |
| --- | --- |
| 視窗 |
| 阿拉伯語(Windows) | Windows-1256 |
| 波羅的海(Windows) | Windows-1257 |
| 中歐(Windows) | Windows-1250 |
| 西里爾文(Windows) | Windows-1251 |
| 希臘文(Windows) | Windows-1253 |
| 希伯來語(Windows) | Windows-1255 |
| 泰語(Windows) | TIS-620 |
| 土耳其語(Windows) | Windows-1254 |
| 越南文(Windows) | Windows-1258 |
| 西歐(Windows) | Windows-1252 |
| ISO標準 |
| 阿拉伯文(ISO) | ISO-8859-6 |
| 波羅的海(ISO) | ISO-8859-4 |
| 中歐(ISO) | ISO-8859-2 |
| 西里爾文(ISO) | ISO-8859-5 |
| 愛沙尼亞語(ISO) | ISO-8859-13 |
| 希臘文(ISO) | ISO-8859-7 |
| 希伯來語(ISO邏輯) | ISO-8859-8-l |
| 希伯來語(ISO-Visual) | ISO-8859-8 |
| 拉丁文9(ISO) | ISO-8859-15 |
| 土耳其文(ISO) | ISO-8859-9 |
| 西歐(ISO) | ISO-8859-1 |
| 其他 |
| 簡體中文(GB18030) | GB18030 |
| 簡體中文(GB2312) | GB2312 |
| 簡體中文(HZ) | 赫茲 |
| 繁體中文(Big5) | 大5 |
| 日語(Shift-JIS) | Shift\_JIS |
| 日語(EUC) | EUC-JP |
| 韓語 | EUC-KR |
| Unicode(UTF-8) | UTF-8 |
Internet Explorer無法識別某些較晦澀的字符編碼,因此必須使用表查找實名是很麻煩的,因此,我建議使用Mozilla Firefox來查找您的字符編碼。
## 查找嵌入式編碼
此時,您可能會問:“我們是否已經找到編碼?”事實證明,Web開發人員可以在多個地方指定字符編碼,并且在`META`標記中可以找到一個這樣的地方:
~~~
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
~~~
您可以在`HEAD`HTML文檔的部分中找到此內容。右邊的文本`charset=`是“聲明的”編碼:HTML聲稱是這種編碼,但是實際上是否如此取決于其他因素。現在,請注意您的`META`標簽是否聲明:
1. 字符編碼與瀏覽器報告的字符編碼相同,
2. 字符編碼與瀏覽器的字符編碼不同,或者
3. 根本沒有`META`標簽!(恐怖,恐怖!)
## 固定編碼
這里給出的建議是將頁面作為普通文本`text/html`。`application/xml`或必須使用不同的做法`application/xml+xhtml`,有關更多信息,請參見[XHTML媒體類型上的W3C文檔](http://www.w3.org/TR/2002/NOTE-xhtml-media-types-20020430/)。
如果您的`META`編碼和實際編碼相符,請機靈!您可以跳過此部分。如果他們不...
### 沒有嵌入式編碼
在這種情況下,您需要在`META`網站中添加適當的標記。就像復制粘貼上面的代碼片段并將UTF-8替換為實際編碼的MIME名稱一樣簡單。
> 對于所有那些懷疑者,有一個很好的理由為什么應該明確說明字符編碼。當不告知瀏覽器文本的字符編碼是什么時,它必須猜測:有時猜測是錯誤的。黑客可以操縱這種猜測,以使XSS越過過濾器,然后欺騙瀏覽器將其作為活動代碼執行。[Google UTF-7漏洞](http://shiflett.org/archive/177)就是一個很好的例子。
>
> `META`只要您的網絡服務器發送正確的Content-Type標頭,您就可以不用指定標簽的字符編碼就可以擺脫困境,但是為什么要冒險呢?此外,如果用戶下載HTML文件,則不再有任何Web服務器來定義字符編碼。
### 嵌入式編碼不同意
這是一個非常普遍的錯誤:另一個消息來源是告訴瀏覽器字符編碼是什么,并且覆蓋了嵌入式編碼。該來源通常是網絡服務器(即Apache)發送的Content-Type HTTP標頭。與頁面一起發送的通常的Content-Type標頭可能如下所示:
~~~
內容類型:text / html;字符集= ISO-8859-1
~~~
請注意,這里有一個charset參數:這是Web服務器告訴瀏覽器字符編碼的方式,就像`META`我們之前接觸過的標簽一樣。
> 實際上,對于`META`無法發送標頭的上下文(例如,沒有Web服務器的本地存儲文件),該標簽旨在代替HTTP標頭。因此,名稱`http-equiv`(等效于HTTP)。
解決此問題的方法有兩種:更改`META`標簽以匹配HTTP標頭,或更改HTTP標頭以匹配`META`標簽。我們如何知道該怎么辦?它取決于網站的內容:畢竟,標題和標簽只是描述網頁上實際字符的方式。
如果您的網站:
...僅使用ASCII字符,
兩種方法都可以,但是我建議將兩者都切換為UTF-8(稍后再介紹)。
...使用特殊字符,它們可以正確顯示,
將嵌入的編碼更改為服務器編碼。
...使用特殊字符,但用戶經常抱怨它們出現亂碼,
將服務器編碼更改為嵌入式編碼。
更改META標簽很容易:只需將舊編碼換成新編碼即可。但是,更改服務器(HTTP標頭)編碼會稍微困難一些。
### 更改服務器編碼
#### PHP header()函數
解決此問題的最簡單方法是自己通過編程語言發送編碼。由于您使用的是HTML Purifier,因此我假設使用PHP,盡管用[其他語言](http://www.w3.org/International/O-HTTP-charset#scripting)進行類似的操作并不難。合適的代碼是:
~~~
標頭('Content-Type:text / html; charset = UTF-8');
~~~
...使用您的嵌入式編碼替換UTF-8。此代碼必須在任何輸出之前出現,因此請注意應用程序中的空白(即,輸出之前的任何空白,除了標記內的空白)。
#### PHP ini指令
PHP還有一個簡潔的ini指令,可以節省您的標頭調用:`[default_charset](http://php.net/ini.core#ini.default-charset)`。使用此代碼:
~~~
ini_set('default_charset','UTF-8');
~~~
...也可以解決問題。如果PHP作為Apache模塊運行(而不是作為FastCGI運行,請查閱[phpinfo](http://php.net/phpinfo)()了解詳細信息),您甚至可以使用htaccess在多個PHP文件中應用此屬性:
~~~
php_value default_charset“ UTF-8”
~~~
> 與所有INI指令一樣,這也可以放在php.ini文件中。一些托管服務提供商允許您自定義自己的php.ini文件,要求您的支持以獲取詳細信息。采用:
>
> ~~~
> default_charset =“ utf-8”
> ~~~
#### 非PHP
無論出于何種原因,您都可能需要在非PHP文件(通常是普通HTML文件)上設置字符編碼。這樣做更像是一個命中注定的過程:取決于用作網絡服務器的軟件和該軟件的配置,某些技術可能有效或無效。
#### .htaccess
在Apache上,您可以使用.htaccess文件來更改字符編碼。我將參考[W3C](http://www.w3.org/International/questions/qa-htaccess-charset)進行深入的解釋,但是歸結為創建一個名為.htaccess的文件,其內容如下:
~~~
AddCharset UTF-8 .html
~~~
在將UTF-8替換為您要使用的字符編碼的情況下,.html是將應用到的文件擴展名。然后,將直接在您放置此文件的目錄中或該目錄的子目錄中為任何文件設置此字符編碼。
如果您感到特別勇氣,可以使用:
~~~
添加默認字符集 UTF-8
~~~
...這將更改Apache添加到不具有任何Content-Type參數的任何文檔中的字符集。出于安全原因,該指令(默認配置文件將其設置為iso-8859-1)可能是標題與`META`標簽不匹配的原因。如果您不希望Apache不參與字符編碼,則可以告訴它根本不發送任何內容:
~~~
AddDefaultCharset關
~~~
...使內部字符集聲明(通常是`META`標簽)成為字符編碼信息的唯一來源。在這些情況下,*特別*重要的是要確保您`META`的頁面上有有效的標記,并且之前的所有文本均為ASCII。
> 這些指令也可以放在Apache的httpd.conf文件中,但是在大多數共享托管情況下,您將無法編輯此文件。
#### 文件擴展名
如果不允許使用.htaccess文件,則通常可以背負Apache的默認AddCharset聲明,以使文件具有適當的擴展名。這是Apache的默認字符集聲明:
| 字符集 | 文件擴展名 |
| --- | --- |
| ISO-8859-1 | .iso8859-1 .latin1 |
| ISO-8859-2 | .iso8859-2 .latin2 .cen |
| ISO-8859-3 | .iso8859-3 .latin3 |
| ISO-8859-4 | .iso8859-4 .latin4 |
| ISO-8859-5 | .iso8859-5 .latin5 .cyr .iso-ru |
| ISO-8859-6 | .iso8859-6 .latin6 .arb |
| ISO-8859-7 | .iso8859-7 .latin7 .grk |
| ISO-8859-8 | .iso8859-8 .latin8 .heb |
| ISO-8859-9 | .iso8859-9 .latin9 .trk |
| ISO-2022-JP | .iso2022-jp .jis |
| ISO-2022-KR | .iso2022-kr .kis |
| ISO-2022-CN | .iso2022-cn。順式 |
| 大5 | .big5 .big5 .b5 |
| WINDOWS-1251 | .cp-1251 .win-1251 |
| CP866 | .cp866 |
| KOI8-r | .koi8-r .koi8-ru |
| KOI8-RU | .koi8-uk .ua |
| ISO-10646-UCS-2 | .ucs2 |
| ISO-10646-UCS-4 | .ucs4 |
| UTF-8 | .utf8 |
| GB2312 | .gb2312 .gb |
| utf-7 | .utf7 |
| EUC-TW | .euc-tw |
| EUC-JP | .euc-jp |
| EUC-KR | .euc-kr |
| shift\_jis | .sjis |
因此,例如,一個名為`page.utf8.html`或的文件`page.html.utf8`可能會附加UTF-8字符集發送,不同之處在于,如果有`AddCharset charset .html`聲明,它將覆蓋.utf8擴展名`page.utf8.html`(優先級從右移到左)。默認情況下,Apache沒有此類聲明。
#### Microsoft IIS
如果有人可以提供有關如何配置Microsoft IIS來更改字符編碼的信息,我將不勝感激。
### XML格式
`META`標簽是最常見的嵌入式編碼來源,但它們也可以來自其他地方:XML聲明。他們看起來像:
~~~
<?xml版本=“ 1.0”編碼=“ UTF-8”?>
~~~
...并且最常見于XML文檔(包括XHTML)中。
對于XHTML,理論上,此XML聲明會覆蓋`META`標記。實際上,只有在XHTML實際上是合法的XML而不是HTML時才發生這種情況,這幾乎永遠不會由于Internet Explorer的缺乏而支持`application/xhtml+xml`(盡管通常認為這樣做是一種[很好的做法,](http://www.hixie.ch/advocacy/xhtml)并且XHTML要求這樣做)1.1規范)。
但是,對于XML,此XML聲明非常重要。由于大多數Web服務器未配置為發送.xml文件的字符集,因此這是解析器唯一要做的事情。此外,XML文件的默認設置為UTF-8,它通常使用更常見的ISO-8859-1編碼來對頭(您在亂碼的RSS提要中看到了這一點)。
簡而言之,如果您使用XHTML并遇到了添加XML聲明的麻煩,請確保它與您的`META`標簽(僅在text / html中提供的標簽)和HTTP標頭配合使用。
### 流程內部
本部分不是必讀部分,但可能會回答您有關所有此字符編碼軌跡的最新信息。如果您有興趣進入下一個階段,請跳過本節。
我們所有人都在研究并處理多種字符編碼源之后,一個邏輯問題是“為什么會有這么多選擇?”為了回答這個問題,我們必須回退字符編碼的定義:它們允許程序將字節解釋為人類可讀的字符。
因此,出現了一個雞蛋問題:必須使用字符編碼來解釋文檔的文本。一個`META`標簽是在文檔的文本。該`META`標記給出了字符編碼。`META`如果我們不知道標記的字符編碼,如何確定其內容呢?如果我們不知道`META`標簽的內容,我們如何找出字符編碼?
對我們來說幸運的是,我們需要編寫的字符`META`都是ASCII的,這在當今通常使用的每種字符編碼中都非常普遍。因此,網絡瀏覽器所需要做的就是一直解析直到到達Content-Type標記,提取字符編碼標記,然后根據此新信息重新解析文檔。
顯然,這很復雜,因此瀏覽器更喜歡更簡單,更有效的解決方案:從文檔本身之外的其他位置(即HTTP標頭)獲取字符編碼,這令無法設置這些標頭的HTML作者非常惱火。
## 為什么選擇UTF-8?
因此,您已經經歷了所有麻煩,以確保服務器和嵌入式字符都正確排列并存在。做得好:在這一點上,您可以知道自己的頁面不容易受到字符編碼樣式XSS攻擊的影響,從而退出并輕松自在。但是,就像擁有字符編碼比完全沒有字符編碼要好一樣,擁有UTF-8作為字符編碼要比具有其他隨機字符編碼要好,下一步就是轉換為UTF-8。但為什么?
### 國際化
許多軟件項目在某一時刻突然意識到它們應該支持多種語言。即使是一種語言的常規用法,有時也需要偶爾使用特殊字符,這并不奇怪,您的字符集中沒有該特殊字符。有時,開發人員通過添加對多種編碼的支持來解決此問題:使用中文時,使用Big5,使用日語時,使用Shift-JIS,使用希臘語等。其他時候,他們使用帶有熱情的字符引用。
但是,UTF-8消除了對任何這些復雜措施的需要。使系統使用UTF-8并針對瀏覽器無法控制的源進行調整后(稍后會詳細介紹),UTF-8才可以使用。您可以將它同時用于任何一種語言,甚至可以用于多種語言,您不必擔心管理多種編碼,也不必使用那些對用戶不友好的實體。
### 方便使用的
使用Latin-1(ISO-8859-1)編碼的網站有時需要超出其范圍的特殊字符,通常會使用字符實體引用來達到預期的效果。例如,可以寫入θ`θ`,而與希臘字母的字符編碼支持無關。
這對于限制使用特殊字符效果很好,但是說您想要這句話的中文文本:激光,這兩個字是什么意思。與符號編碼的版本如下所示:
~~~
&#28608;&#20809 ;,&#36889;&#20841;&#20491;&#23383;&#26159;&#29978;&#40636;&#24847;&#24605;
~~~
對于我們當中那些真正知道角色實體是什么的人來說,這極為不便,而對于那些不知道這些角色的貧困用戶來說,這是絕對無法理解的!甚至像稍微更用戶友好的“難以理解”的字符實體,`θ`也會使對學習HTML不感興趣的用戶撓頭。另一方面,如果他們在編輯框中看到θ,他們將知道這是一個特殊字符,并對其進行相應處理,即使他們自己不知道如何編寫該字符也是如此。
> 對于最初使用ISO-8859-1的應用程序來說,Wikipedia是一個很好的案例研究,但是當它變得繁瑣而無法支持外語時,便切換為UTF-8。Bot現在實際上將瀏覽文章并將字符實體轉換為它們相應的真實字符,以便于用戶友好和可搜索。有關更多詳細信息,請參見[Meta的特殊字符頁面](http://meta.wikimedia.org/wiki/Help:Special_characters)。
### 形式
當我們站在用戶的立場上時,非UTF-8網絡表單如何處理其字符集之外的字符?除了要討論UTF-8的正確之處,我們還要說明的是如果您不使用UTF-8并且人們嘗試使用字符編碼之外的字符,那么可能會出問題。
問題很大,范圍廣泛,而且很難解決(或者至少很難解決,如果您有時間和資源進行修復,那么最好遷移到UTF-8)。表單提交有兩種類型:`application/x-www-form-urlencoded`一種用于GET,默認情況下用于POST,并且`multipart/form-data`可以由POST使用,并且在您要上傳文件時需要。
以下是[提交和i18n](http://web.archive.org/web/20060427015200/ppewww.ph.gla.ac.uk/~flavell/charset/form-i18n.html)的注釋摘要。該文檔包含許多有用的信息,但是以粗俗的方式編寫,因此在這里我嘗試著重點。(注意:原始文件已經從網絡上消失了,因此我鏈接到Web存檔副本。)[`FORM`](http://web.archive.org/web/20060427015200/ppewww.ph.gla.ac.uk/~flavell/charset/form-i18n.html)
#### `application/x-www-form-urlencoded`
這是GET請求必須使用的Content-Type,而POST請求默認使用。它涉及到無所不在的百分比編碼格式,如下所示:`%C3%86`。由于百分比編碼在字節級別上進行操作,因此沒有確定這種請求的字符編碼的官方方法,因此通常假定它與提交表單的頁面的編碼相同。([RFC 3986](http://tools.ietf.org/html/rfc3986#section-2.5)建議將文本標識符轉換為UTF-8;但是,瀏覽器兼容性差強人意。)如果僅在選擇的字符編碼中使用字符,您將遇到很少的問題。
但是,一旦開始在編碼之外添加字符(這比您想像的要普遍得多:以Microsoft的卷曲“ smart”引號為例),就會發生各種各樣奇怪的事情。根據您使用的瀏覽器,它們可能:
* 將不支持的字符替換為無用的問號,
* 嘗試修復字符(例如:將智能引號替換為常規引號),
* 用字符實體引用替換字符,或者
* 無論如何,以不同的字符編碼與原始編碼混合發送(通常是Windows-1252,而不是散布在8位中的iso-8859-1或UTF-8)
為了適當地防止這些行為,您必須嗅探瀏覽器代理,編譯具有不同行為的數據庫,并對字符串采取適當的轉換操作(而不管Internet Explorer每次出現的一系列極其神秘,隨機和破壞性的錯誤)等一下)。或者您可以使用UTF-8并放心,因為UTF-8支持每個字符,所以這一切都不可能發生。
#### `multipart/form-data`
多部分表單提交消除了百分比編碼所帶來的許多歧義:服務器現在可以顯式地請求某些編碼,并且客戶端可以在表單提交期間顯式地告訴服務器字段的編碼。
您可以通過兩種方法使用此功能:將其保留為未設置狀態,然后讓瀏覽器以與頁面相同的編碼進行發送,或者將其設置為UTF-8,然后在服務器端執行另一次轉換。每種方法都有缺陷,尤其是前者。
如果告訴瀏覽器以與頁面相同的編碼發送表單,則仍會遇到如何處理超出字符編碼范圍的字符的麻煩。行為再次有所不同:Firefox 2.0將它們轉換為字符實體引用,而Internet Explorer 7.0則使它們難以理解。為了嚴肅的國際化目的,這不是一個選擇。
另一種可能性是將Accept-Encoding設置為UTF-8,這引出了一個問題:您為什么不對所有內容都使用UTF-8?這條路線更可口,但是有一個值得注意的警告:您的數據將以UTF-8格式輸入,因此您必須將其顯式轉換為您喜歡的本地字符編碼。
我出于思想上的原因反對這種方法:當您本來可以轉換為UTF-8時,您將更深入自己。而且,當然,您不能對GET請求使用此方法。
### 很好的支持
如今,幾乎所有狂野的現代瀏覽器都完全支持UTF-8和Unicode:麻煩的情況可以用一只手的手指來計算,這些瀏覽器通常也遇到其他字符編碼的麻煩。用戶通常會遇到的問題是由于缺少合適的字體來顯示字符(再一次,這適用于所有字符編碼和HTML實體)或Internet Explorer缺乏智能字體選擇(可以解決)。
我們將在“遷移”部分中詳細介紹如何處理瀏覽器世界中的一些極端情況,但是請放心,如果正確完成轉換,轉換為UTF-8不會導致用戶困擾您破碎的頁面。
### HTML凈化器
最后,我們進入HTML Purifier。HTML Purifier是為處理UTF-8而構建的:否則,任何指示都是編碼器的結果,該編碼器將文本從您的首選編碼轉換為UTF-8,然后再次轉換。HTML Purifier永遠不會觸碰其他任何東西,而是將其留給模塊iconv來完成骯臟的工作。
但是,這種方法并不完美。iconv根本不了解HTML字符實體。為了防止復雜的轉義方案,HTML Purifier在處理文本之前將所有字符和數字實體引用標準化。這導致了一個重要的后果:
**目標字符集不支持的任何字符,無論它是以字符實體引用還是原始字符的形式,都將被靜默忽略。**
此原則的示例正在起作用:假設您已經`θ`在HTML中使用,但是輸出使用的是Latin-1(可以理解,它不理解希臘語),則會發生以下過??程(假設您已使用%Core正確設置了編碼.Encoding):
* 該`Encoder`會從ISO 8859-1轉換文本為UTF-8(注意,theta是保存在這里,因為它實際上并未使用任何非ASCII字符):`θ`
* 在`EntityParser`將改變所有命名和數字字符實體到他們相應的原始UTF-8當量:`θ`
* HTML Purifier處理代碼:`θ`
* 在`Encoder`現在將來自UTF-8 ISO 8859-1背課文。由于ISO 8859-1不支持希臘語,因此它將被忽略或替換為問號:`?`
此行為是非常不令人滿意的。它是國際應用程序的突破者,對于偶爾需要特殊字符的省級靈魂可能會有些惱火。從1.4.0版本開始,HTML Purifier使用%Core.EscapeNonASCIICharacters提供了稍微更可口的解決方法。現在,該過程如下所示:
* 的`Encoder`編碼為UTF-8變換:`θ`
* 該`EntityParser`變換實體:`θ`
* HTML Purifier處理代碼:`θ`
* 該`Encoder`替換數字實體引用的所有非ASCII字符:`θ`
* 為了達到良好的效果,請將`Encoder`編碼轉換回原始`θ`格式(對于99%的編碼來說,這絕對是不必要的):(請記住,全都是ASCII!)
...這意味著這僅對偶爾進入Unicode字符領域很有用,而中文或日文文本完全不可接受。更大的缺點是,假設輸入編碼實際上*是*支持theta的ISO-8859-7,*則*無論如何該字符都將轉換為字符實體引用!(編碼器不區分)。
當前的功能是關于HTML Purifier在永恒的歲月中所處的位置。HTML Purifier可以嘗試保留字符引用的原始形式,以便可以將它們替換回去,只有DOM擴展名不可逆轉地將其殺死。HTML Purifier也可以嘗試變得聰明,只轉換目標編碼不支持的非ASCII字符,但這將需要重新實現具有HTML意識的iconv,而我不會這樣做。
就是這樣:要么是UTF-8,要么是殘廢的國際支持。您的選擇!(而且我這里并不是在諷刺:有些人可能不太在乎其他語言)。
## 遷移到UTF-8
因此,您已經決定硬著頭皮,并想要遷移到UTF-8。請注意,這不是為膽小者準備的,您應該期望該過程花費的時間比您認為的要長。
通常的想法是,將所有現有文本轉換為UTF-8,然后將我們前面討論的所有標頭和META標記設置為UTF-8。這樣做的方法有很多:您可以編寫一個轉換腳本,該腳本在數據庫中運行并將所有內容重新編碼為UTF-8,或者當有人閱讀該頁面時,您可以即時進行轉換。詳細信息取決于您的系統,但是我將介紹一些可能會使您絆倒的更細微的遷移點。
### 配置數據庫
大多數現代數據庫(最著名的開源數據庫是MySQL 4.1+和PostgreSQL)都支持字符編碼。從邏輯上講,如果要切換到UTF-8,則需要確保數據庫也知道該更改。但是有一些警告:
#### 合法方法
用于指定字符編碼的SQL語法方面的標準化是眾所周知的。有關如何正確執行此操作,請參閱各自數據庫的文檔。
對于[MySQL](http://dev.mysql.com/doc/refman/5.0/en/charset-conversion.html),`ALTER`將神奇地為您執行字符編碼轉換。但是,您必須確保該列中的文字是它所說的:如果將Shift-JIS放在ISO 8859-1列中,則當您嘗試將其轉換為UTF-時,MySQL將不可逆轉地處理該文本。 8。您必須將其轉換為二進制字段,將其轉換為Shift-JIS字段(實際編碼),然后最終轉換為UTF-8。許多網站的頁面不可逆地受到破壞,因為他們沒有意識到自己一直在欺騙字符編碼;不要成為下一個受害者。
對于[PostgreSQL](http://www.postgresql.org/docs/8.2/static/multibyte.html),似乎沒有直接的方法可以更改數據庫的編碼(從8.2版本開始)。您將必須轉儲數據,然后將其重新導入到新表中。確保正確設置了客戶端編碼:這就是PostgreSQL知道執行編碼轉換的方式。
很多時候,還會詢問您新列的“排序規則”。排序規則是DBMS對文本進行排序的方式,例如將B,C和A排序為A,B和C(當您使用泰語和日語等語言時,問題變得異常復雜)。如有疑問,使用默認設置通常是一個安全的選擇。
一旦完成所有的轉換,您仍然必須記住使用`SET NAMES`(標準SQL,通常支持)在每個數據庫連接上正確設置客戶端編碼(您的編碼)。
#### 二元
由于上述兼容性問題,存儲UTF-8文本的一種更可互操作的方法是將其填充為二進制數據類型。`CHAR`成為`BINARY`,`VARCHAR`成為`VARBINARY`,`TEXT`成為`BLOB`。這樣做可以為您省去很多麻煩:
* 二進制數據類型的語法非常易于移植,
* MySQL 4.0*不*支持字符編碼,因此,如果要支持字符編碼,則*必須*使用二進制,
* 從5.1版本開始,MySQL不支持四個字節的UTF-8字符,這些字符表示超出基本多語言平面的字符,并且
* 您將永遠不必擔心DBMS太聰明,并在不需要時嘗試轉換文本。
MediaWiki是一個非常著名的國際應用程序,由于第三點,它使用二進制字段來存儲其數據。
當然也有缺點:
* 由于PHPMyAdmin等數據庫工具被聲明為二進制文件,因此無法為您提供內聯文本編輯功能,
* 這在語義上是不正確的:它實際上是文本而不是二進制文件(位于數據庫中),
* 除非您使用上面提到的非便攜式向導,否則您必須自己更改編碼(通常,您會即時進行編碼),并且
* 您將沒有排序規則。
根據您的情況選擇。
### 文本編輯器
對于面向平面文件的系統,通常會負責將現有文本和HTML文件的一部分轉換為UTF-8,并確保所有上傳的新文件都經過正確編碼。再一次,我只能模糊地指出轉換現有文件的正確方向:確保備份,確保使用[iconv](http://php.net/ref.iconv)(),并確保知道文件的原始字符編碼是(或取決于)在系統的整潔度上)。
但是,我可以針對文本編輯器提供更具體的建議。眾所周知,許多文本編輯器都支持Unicode。要了解編輯器的工作方式,您可以查看[此列表](http://www.alanwood.net/unicode/utilities_editors.html)或[Wikipedia的列表。](http://en.wikipedia.org/wiki/Comparison_of_text_editors#Encoding_support)我個人使用的是Notepad ++,它在使用UTF-8時就像一個魅力。通常,您將必須通過一些對話(通常是“另存為”或“格式”)**明確**告訴編輯器您要使用的編碼。編輯器通常會提供“ Unicode”作為保存方法,這是模棱兩可的。確保您知道它們是否真正表示UTF-8或UTF-16(這是Unicode的另一種形式)。
需要注意的兩件事是編輯器是否支持**字體混合**(一個文檔中有多種字體)以及是否添加**BOM**。字體混合非常重要,因為字體很少支持人類已知的每種語言:為了靈活起見,編輯者必須能夠從這里一點點拿走一點,否則所有的漢字都將變成漂亮的盒子。我們將在下面討論BOM。
### 字節順序標記(標題已發送!)
BOM([字節順序標記](http://en.wikipedia.org/wiki/Byte_Order_Mark))是一個神奇的,不可見的字符,放置在UTF-8文件的開頭,用于告訴人們編碼是什么以及文本的字節序是什么。這也是不必要的。
因為它是不可見的,所以當它開始做本不應該做的事情時,常常會讓人感到驚訝。例如,此PHP文件:
~~~
BOM <?php
header('Location:index.php');
?>
~~~
...將會因所有過于熟悉的標**頭已發送**PHP錯誤而失敗。而且因為BOM是不可見的,所以這個罪魁禍首將不會被注意到。我的建議是僅在PHP頁面中使用ASCII,但如果必須的話,請確保在不使用BOM表的情況下保存該頁面。
> 錯誤所指的標頭是**HTTP標頭**,這些**標頭**在發送任何HTML之前先發送給瀏覽器以告知各種信息。輸出任何常規文本(是的,物料清單算作普通文本)后,必須發送標頭,并且您再也不能發送了。因此,錯誤。
如果您正在閱讀文本文件以插入到另一頁的中間,強烈建議(但并非絕對必要)通過以下方式替換BOM的UTF-8字節序列`"\xEF\xBB\xBF"`:
~~~
$ text = str_replace(“ \ xEF \ xBB \ xBF”,``,$ text);
~~~
### 字型
一般來說,遇到字體問題的人分為兩類:
* 那些想要使用一種非常晦澀難懂的語言的人,即使母語為母語的人也幾乎沒有這種支持,并且
* 那些文字的主要語言得到了很好的支持,但是偶爾不支持這些字符的語言。
是的,在Sinhalese網站上總是有英語使用者出現在網站上,并且字體不正確。但是,碰巧沒有正確字體的英語用戶可能仍然無法閱讀僧伽羅語。因此,我們將處理其他兩種情況。
#### 晦澀的腳本
如果您運行孟加拉語網站,則可能會得到那些希望閱讀您的網站但收到大量問號或其他無意義字符的用戶的評論。要解決此問題,需要安裝字體或語言包,該字體或語言包通常高度依賴于語言。[這是](http://bn.wikipedia.org/wiki/%E0%A6%89%E0%A6%87%E0%A6%95%E0%A6%BF%E0%A6%AA%E0%A7%87%E0%A6%A1%E0%A6%BF%E0%A6%AF%E0%A6%BC%E0%A6%BE:Bangla_script_display_and_input_help)孟加拉語幫助文件[的示例](http://bn.wikipedia.org/wiki/%E0%A6%89%E0%A6%87%E0%A6%95%E0%A6%BF%E0%A6%AA%E0%A7%87%E0%A6%A1%E0%A6%BF%E0%A6%AF%E0%A6%BC%E0%A6%BE:Bangla_script_display_and_input_help)。我肯定那里也有其他人。您只需要將用戶指向適當的幫助文件。
#### 偶爾使用
一個很好的例子,當您看到嵌入在非常平淡的ASCII中的一些非常晦澀的Unicode字符時,是[國際語音字母(IPA)的字母](http://en.wikipedia.org/wiki/International_Phonetic_Alphabet),用于以非常標準的方式指定發音(您可能會看到它們在字典中的時間)。您的平均字體可能不支持所有IPA字符,例如?(雙音)或?(發聲后齒擦音)。那么,瀏覽器性能不佳怎么辦?字體混合!諸如Mozilla Firefox和Internet Explorer 7的智能瀏覽器將從其他字體中借用字形,以確保所有字符都能正確顯示。
但是,如果瀏覽器不智能并且恰好是全世界使用最廣泛的瀏覽器,會發生什么?當一個字符不存在時,Microsoft IE 6不夠聰明,無法從其他字體中借用,因此通常您會被一個漂亮的大字符拍打。為了使一切正常,MSIE 6需要一些微調。您可以將其配置為使用其他字體來呈現文本,但是可以通過有選擇地將特殊字符塊的字體更改為已知的Unicode字體來達到相同的效果。
幸運的是,維基百科的人們已經為您完成了所有繁重的工作。從此處獲取CSS:[Common.css](http://en.wikipedia.org/wiki/MediaWiki:Common.css),并搜索“ .IPA”。還有一些其他類可用于其他目的,請查看[此頁面](http://meta.wikimedia.org/wiki/Help:Special_characters#Displaying_Special_Characters)以獲取更多詳細信息。對于那些懶惰的人,這應該可以工作:
~~~
.Unicode {
字體家族:Code2000,“ TITUS Cyber??bit Basic”,“ Doulos SIL”,
“ Chrysanthi Unicode”,“ Bitstream Cyber??bit”,
“ Bitstream Cyber??Base”,Throomanes,Gentium,GentiumAlt,
“ Lucida Grande”,“ Arial Unicode MS”,“ Microsoft Sans Serif”,
“ Lucida Sans Unicode”;
字體家族/ ** /:inherit; / *為IE6以外的所有人重置字體* /
}
~~~
標準用法遵循`<span class="Unicode">Crazy Unicode stuff here</span>`。通常不需要修復[Windows字形列表](http://en.wikipedia.org/wiki/Windows_Glyph_List_4)中的字符,但是對于其他任何事情,您可能都希望安全播放。除非,當然,除非您不關心IE6用戶。
### 處理函數中的可變寬度
當人們聲稱PHP6將解決我們所有的Unicode問題時,他們被誤導了。它不會解決任何上述問題。但是,它將解決我們將要討論的問題:在PHP中處理UTF-8文本。
PHP(從PHP5開始)根本沒有意識到UTF-8的存在(有一些值得注意的例外)。有時,這會引起問題,而其他時候則不會。到目前為止,我們避免討論UTF-8的體系結構,因此,我們首先要問什么是UTF-8?是的,它支持Unicode,是的,它是可變寬度。其他特點:
* 每個字符的字節序列都是唯一的,永遠不會在另一個字符的字節序列內找到,
* UTF-8最多可以使用四個字節來編碼字符,
* 必須檢查UTF-8文本的格式是否正確,
* 純ASCII也是有效的UTF-8,并且
* 二進制排序將按照與Unicode相同的順序對UTF-8進行排序。
這些特征中的每一個都以不同的方式影響文本處理的不同領域。解釋這些含義的確切含義超出了本文檔的范圍。PHPWact提供了一個很好的[參考文檔](http://www.phpwact.org/php/i18n/utf-8),說明了對每個功能的期望,盡管在某些方面涉及面很廣。他們關于[字符集的](http://www.phpwact.org/php/i18n/charsets)更一般的注釋也值得一看,以獲取有關UTF-8的信息。處理Unicode文本時的一些經驗法則:
* 請勿使用以下功能:
* ...轉換大小寫(strtolower,strtoupper,ucfirst,ucwords)
* ...聲稱不區分大小寫(str\_ireplace,stristr,strcasecmp)
* 使用以下函數之前請三思:
* ...計算字符(strlen將返回字節,而不是字符; str\_split和word\_wrap可能會損壞)
* ...將字符轉換為實體引用(UTF-8不需要實體)
* ...執行非常復雜的字符串處理(\* printf)
注意:此列表僅適用于UTF-8編碼的文本:如果您擁有100%確定是ASCII的字符串,請成為我的客人并使用`strtolower`(HTML Purifier使用此功能。)
無論如何,請始終以字節為單位,而不是以字符為單位。如果使用strpos()查找字符的位置,它將以字節為單位,但這通常無關緊要,因為substr()也可以使用字節索引操作!
您還需要確保您的UTF-8格式正確,并且可能需要替換其中一些功能。我建議使用Harry Fuecks的[PHP UTF-8](http://phputf8.sourceforge.net/)庫,而不是直接使用mb\_string。HTML Purifier還定義了一些有用的UTF-8兼容功能:`Encoder.php`在`/library/HTMLPurifier/`目錄中檢出。
## 進一步閱讀
好吧,就是這樣。希望該文檔對了解UTF-8的工作原理起到了非常實用的跳板作用。您可能已經決定不遷移:很好,只知道輸出將發生什么以及可能收到的錯誤報告。
許多其他開發人員已經討論了Unicode,UTF-8和國際化的主題,我想請他們對字符集和編碼進行更深入的研究。
* [絕對最低每一個軟件開發人員絕對,積極必須知道的關于Unicode和字符集(沒有借口!)](http://www.joelonsoftware.com/articles/Unicode.html)由Joel Spolsky的,提供了一個*非常*以Unicode和字符集在總體上是好的高水平的樣子。
* [Wikipedia上](http://en.wikipedia.org/wiki/UTF-8)的UTF-8為UTF-8的內幕提供了許多有用的細節,盡管對于一開始不太了解Unicode的人來說可能有些反感。
- php更新內容
- PHP PSR 標準規范
- 輔助查詢(*)
- composer項目的創建
- composer安裝及設置
- composer自動加載講解
- phpsdudy的composer操作
- git
- Git代碼同時上傳到GitHub和Gitee(碼云)
- Git - 多人協同開發利器,團隊協作流程規范與注意事項
- 刪除遠程倉庫的文件
- github查詢方法
- 錯誤
- 其他
- php.ini
- php配置可修改范圍
- php超時
- 防跨目錄設置
- 函數可變參數
- 【時間】操作
- 時間函數例子
- Date/Time 函數(不包含別名函數)
- DateTime類別名函數
- 【數字】操作
- 【字符串】操作
- 【數組】操作
- 排序
- 合并案例
- empty、isset、is_null
- echo 輸出bool值
- if真假情況
- 流程控制代替語法【if (條件): endif;】
- 三元運算
- 運算符優先級
- 常量
- define與const(php5.3) 類常量
- 遞歸
- 單元測試
- 面向對象
- 對象(object) 與 數組(array) 的轉換
- php網絡相關
- 支持的協議和封裝協議(如http,php://input)
- php://協議
- file://協議
- http(s)://協議
- ftp(s)://協議
- zip://, bzip2://, zlib://協議
- data://協議
- glob://協議
- expect://協議
- phar://
- ssh2
- rar://
- ogg://
- 上下文(Context)選項和參數
- 過濾器
- http請求及模擬登錄
- 常用的header頭部定義匯總
- HTTP響應頭和請求頭信息對照表
- HTTP請求的返回值含義說明
- content-type對照表
- Cache-Control對照
- curl函數
- 防止頁面刷新
- telnet模擬get、post請求
- 三種方式模擬表單發布留言
- 模擬登陸
- 防盜鏈
- php+mysql模擬隊列發送郵件
- socket
- 使用websocket實現php消息實時推送完整示例
- streams
- Stream函數實現websocket
- swoole
- 網絡編程基本概念
- 全局變量域超全局變量
- 超全局變量
- $_ENV :存儲了一些系統的環境變量
- $_COOKIE
- $_SESSION
- $_FILES
- $_SERVER
- 正則
- php正則函數
- 去除文本中的html、xml的標簽
- 特殊符號
- \r\n
- 模式修正符
- 分組
- 斷言(環視?)
- 條件表達式
- 遞歸表達式 (?R)
- 固化分組
- 正則例子
- 提取類文件的公共方法
- 抓取網頁內容
- 匹配中文字符
- 提取sql日志文件
- 框架
- 文件操作
- 自動加載spl_autoload_register
- 文件加載
- 文件的上傳下載
- 常見的mimi類型
- 文件斷點續傳
- 下載文件防盜鏈
- 破解防盜鏈
- 將字節轉為人可讀的單位
- 無限分類
- 短信驗證碼
- 短信寶
- 視頻分段加載
- 隱藏地址
- MPEG DASH視頻分片技術
- phpDoc注釋
- @錯誤抑制符
- 字符編碼
- PHP CLI模式開發
- CGI、FastCGI和PHP-FPM關系圖解
- No input file specified的解決方法
- SAPI(PHP常見的四種運行模式)
- assert斷言
- 輪詢(Event Loop)
- 異常處理
- 異常分類
- php系統異常
- 錯誤級別
- set_error_handler
- set_exception_handler
- register_shutdown_function
- try catch
- tp5異常處理類解析
- 文件上傳相關設置
- 進程/線程/協程
- 協程
- 什么是協程
- 引用&
- Heredoc和Nowdoc語法
- 類基礎
- 系統預定義類
- pdo
- 類的三大特性:封裝,繼承,多態
- 魔術方法
- extends繼承
- abstract 抽象類
- interface 接口(需要implements實現)
- 抽象類和接口的區別
- 多態
- static
- final
- serialize與unserialize
- instanceof 判斷后代子類
- 類型約束
- clone克隆
- ::的用法
- static::class、self::class
- new self()與new static()
- this、self、static、parent、super
- self、static、parent:后期靜態綁定
- PHP的靜態變量
- php導入
- trait
- 動態調用類方法
- 參數及類型申明
- 方法的重載覆蓋
- return $a && $b
- 類型聲明
- 設計思想
- 依賴注入與依賴倒置
- MVC模式與模板引擎
- 模版引擎
- smarty模版
- 系統變量、全局變量
- 語言切換
- 函數-給函數默認值
- 流程控制-遍歷
- 模版加載
- 模版繼承
- blade
- twig
- Plates
- 創建型模式(創建類對象)--單原二廠建
- (*)單例模式(保證一個類僅有一個實例)
- (*)工廠模式(自動實例化想要的類)
- 原型模式(在指定方法里克隆this)
- 創建者模式(建造者類組裝近似類屬性)
- 結構型模式 --橋(幫)組享外帶裝適
- 適配器模式(Adapter 用于接口兼容)
- 橋接模式(方法相同的不同類之間的快速切換)
- 裝飾模式(動態增加類對象的功能 如游戲角色的裝備)
- 組合模式(用于生成類似DOMDocument這種節點類)
- 外觀模式(門面(Facade)模式 不同類的統一調用)
- 享元模式
- 代理模式
- 行為型模式--觀摩職命狀-備爹在房中潔廁
- (*)觀察者模式
- (*)迭代器模式(Iterator)
- 模板方法模式 Template
- 命令模式(Command)
- 中介者模式(Mediator)
- 狀態模式(State)
- 職責鏈模式 (Chainof Responsibility)
- 策略模式(Strategy)
- 已知模式-備忘錄模式(Memento)
- 深度模式-解釋器模式(Interpreter)
- 深度模式-訪問者模式(Visitor)
- (*)注冊樹(注射器、注冊表)模式
- PHP擴展庫列表
- 函數參考
- 影響 PHP 行為的擴展
- APC擴展(過時)
- APCu擴展
- APD擴展(過時)
- bcompiler擴展(過時)
- BLENC擴展 (代碼加密 實驗型)
- Componere擴展(7.1+)
- Componere\Definition
- Componere\Patch
- Componere \ Method
- Componere\Value
- Componere函數
- 錯誤處理擴展(PHP 核心)
- FFI擴展
- 基本FFI用法
- FFI api
- htscanner擴展
- inclued擴展
- Memtrack擴展
- OPcache擴展(5.5.0內部集成)
- Output Control擴展(核心)
- PHP Options/Info擴展(核心)
- 選項、 信息函數
- phpdbg擴展(5.6+內部集成)
- runkit擴展
- runkit7擴展
- scream擴展
- uopz擴展
- Weakref擴展
- WeakRef
- WeakMap
- WinCache擴展
- Xhprof擴展
- Yac(7.0+)
- 音頻格式操作
- ID3
- KTaglib
- oggvorbis
- OpenAL
- 身份認證服務
- KADM5
- Radius
- 針對命令行的擴展
- Ncurses(暫無人維護)
- Newt(暫無人維護)
- Readline
- 壓縮與歸檔擴展
- Bzip2
- LZF
- Phar
- Rar
- Zip
- Zlib
- 信用卡處理
- 加密擴展
- Crack(停止維護)
- CSPRNG(核心)
- Hash擴展(4.2內置默認開啟、7.4核心)
- Mcrypt(7.2移除)
- Mhash(過時)
- OpenSSL(*)
- 密碼散列算法(核心)
- Sodium(+)
- 數據庫擴展
- 數據庫抽象層
- DBA
- dbx
- ODBC
- PDO(*)
- 針對各數據庫系統對應的擴展
- CUBRID
- DB++(實驗性)
- dBase
- filePro
- Firebird/InterBase
- FrontBase
- IBM DB2
- Informix
- Ingres
- MaxDB
- Mongo(MongoDB老版本)
- MongoDB
- mSQL
- Mssql
- MySQL
- OCI8(Oracle OCI8)
- Paradox
- PostgreSQL
- SQLite
- SQLite3
- SQLSRV(SQL Server)
- Sybase
- tokyo_tyrant
- 日期與時間相關擴展
- Calendar
- 日期/時間(核心)
- HRTime(*)
- 文件系統相關擴展
- Direct IO
- 目錄(核心)
- Fileinfo(內置)
- 文件系統(核心)
- Inotify
- Mimetype(過時)
- Phdfs
- Proctitle
- xattr
- xdiff
- 國際化與字符編碼支持
- Enchant
- FriBiDi
- Gender
- Gettext
- iconv(內置默認開啟)
- intl
- 多字節字符串(mbstring)
- Pspell
- Recode(將要過時)
- 圖像生成和處理
- Cairo
- Exif
- GD(內置)
- Gmagick
- ImageMagick
- 郵件相關擴展
- Cyrus
- IMAP
- Mail(核心)
- Mailparse
- vpopmail(實驗性 )
- 數學擴展
- BC Math
- GMP
- Lapack
- Math(核心)
- Statistics
- Trader
- 非文本內容的 MIME 輸出
- FDF
- GnuPG
- haru(實驗性)
- Ming(實驗性)
- wkhtmltox(*)
- PS
- RPM Reader(停止維護)
- RpmInfo
- XLSWriter Excel操作(*)
- php第三方庫非擴展
- 進程控制擴展
- Eio
- Ev
- Expect
- Libevent
- PCNTL
- POSIX
- 程序執行擴展(核心)
- parallel
- pthreads(*)
- pht
- Semaphore
- Shared Memory
- Sync
- 其它基本擴展
- FANN
- GeoIP(*)
- JSON(內置)
- Judy
- Lua
- LuaSandbox
- Misc(核心)
- Parsekit
- SeasLog(-)
- SPL(核心)
- SPL Types(實驗性)
- Streams(核心)
- stream_wrapper_register
- stream_register_wrapper(同上別名)
- stream_context_create
- stream_socket_client
- stream_socket_server
- stream_socket_accept
- stream_socket_recvfrom
- stream_socket_sendto
- Swoole(*)
- Tidy擴展
- Tokenizer
- URLs(核心)
- V8js(*)
- Yaml
- Yaf
- Yaconf(核心)
- Taint(檢測xss字符串等)
- Data Structures
- Igbinary(7.0+)
- 其它服務
- 網絡(核心)
- Sockets
- socket_create
- socket_bind(服務端即用于監聽的套接字)
- socket_listen(服務端)
- socket_accept(服務端)
- socket_connect(客戶端)
- socket_read
- socket_recv(類似socket_read)
- socket_write
- socket_send
- socket_close
- socket_select
- socket_getpeername
- socket_getsockname
- socket_get_option
- socket_getopt(socket_get_option的別名)
- socket_set_option
- socket_setopt( socket_set_option的別名)
- socket_recvfrom
- socket_sendto
- socket_addrinfo_bind
- socket_addrinfo_connect
- socket_addrinfo_explain
- socket_addrinfo_lookup
- socket_clear_error
- socket_last_error
- socket_strerror
- socket_cmsg_space
- socket_create_listen
- socket_create_pair
- socket_export_stream
- socket_import_stream
- socket_recvmsg
- socket_sendmsg
- socket_set_block
- socket_set_nonblock
- socket_shutdown
- socket_wsaprotocol_info_export
- socket_wsaprotocol_info_import
- socket_wsaprotocol_info_release
- cURL(*)
- curl_setopt
- Event(*)
- chdb
- FAM
- FTP
- Gearman
- Gopher
- Gupnp
- Hyperwave API(過時)
- LDAP(+)
- Memcache
- Memcached(+)
- mqseries
- RRD
- SAM
- ScoutAPM
- SNMP
- SSH2
- Stomp
- SVM
- SVN(試驗性的)
- TCP擴展
- Varnish
- YAZ
- YP/NIS
- 0MQ(ZeroMQ、ZMQ)消息系統
- 0mq例子
- ZooKeeper
- 搜索引擎擴展
- mnoGoSearch
- Solr
- Sphinx
- Swish(實驗性)
- 針對服務器的擴展
- Apache
- FastCGI 進程管理器
- IIS
- NSAPI
- Session 擴展
- Msession
- Sessions
- Session PgSQL
- 文本處理
- BBCode
- CommonMark(markdown解析)
- cmark函數
- cmark類
- Parser
- CQL
- IVisitor接口
- Node基類與接口
- Document
- Heading(#)
- Paragraph
- BlockQuote
- BulletList
- OrderedList
- Item
- Text
- Strong
- Emphasis
- ThematicBreak
- SoftBreak
- LineBreak
- Code
- CodeBlock
- HTMLBlock
- HTMLInline
- Image
- Link
- CustomBlock
- CustomInline
- Parle
- 類函數
- PCRE( 核心)
- POSIX Regex
- ssdeep
- 字符串(核心)
- 變量與類型相關擴展
- 數組(核心)
- 類/對象(核心)
- Classkit(未維護)
- Ctype
- Filter擴展
- 過濾器函數
- 函數處理(核心)
- quickhash擴展
- 反射擴展(核心)
- Variable handling(核心)
- Web 服務
- OAuth
- api
- 例子:
- SCA(實驗性)
- SOAP
- Yar
- XML-RPC(實驗性)
- Windows 專用擴展
- COM
- 額外補充:Wscript
- win32service
- win32ps(停止更新且被移除)
- XML 操作(也可以是html)
- libxml(內置 默認開啟)
- DOM(內置,默認開啟)
- xml介紹
- 擴展類與函數
- DOMNode
- DOMDocument(最重要)
- DOMAttr
- DOMCharacterData
- DOMText(文本節點)
- DOMCdataSection
- DOMComment(節點注釋)
- DOMDocumentFragment
- DOMDocumentType
- DOMElement
- DOMEntity
- DOMEntityReference
- DOMNotation
- DOMProcessingInstruction
- DOMXPath
- DOMException
- DOMImplementation
- DOMNamedNodeMap
- DOMNodeList
- SimpleXML(內置,5.12+默認開啟)
- XMLReader(5.1+內置默認開啟 用于處理大型XML文檔)
- XMLWriter(5.1+內置默認開啟 處理大型XML文檔)
- SDO(停止維護)
- SDO-DAS-Relational(試驗性的)
- SDO DAS XML
- WDDX
- XMLDiff
- XML 解析器(Expat 解析器 默認開啟)
- XSL(內置)
- 圖形用戶界面(GUI) 擴展
- UI
- PHP SPL(PHP 標準庫)
- 數據結構
- SplDoublyLinkedList(雙向鏈表)
- SplStack(棧 先進后出)
- SplQueue(隊列)
- SplHeap(堆)
- SplMaxHeap(最大堆)
- SplMinHeap(最小堆)
- SplPriorityQueue(堆之優先隊列)
- SplFixedArray(陣列【數組】)
- SplObjectStorage(映射【對象存儲】)
- 迭代器
- ArrayIterator
- RecursiveArrayIterator(支持遞歸)
- DirectoryIterator類
- FilesystemIterator
- GlobIterator
- RecursiveDirectoryIterator
- EmptyIterator
- IteratorIterator
- AppendIterator
- CachingIterator
- RecursiveCachingIterator
- FilterIterator(遍歷并過濾出不想要的值)
- CallbackFilterIterator
- RecursiveCallbackFilterIterator
- RecursiveFilterIterator
- ParentIterator
- RegexIterator
- RecursiveRegexIterator
- InfiniteIterator
- LimitIterator
- NoRewindIterator
- MultipleIterator
- RecursiveIteratorIterator
- RecursiveTreeIterator
- 文件處理
- SplFileInfo
- SplFileObject
- SplTempFileObject
- 接口 interface
- Countable
- OuterIterator
- RecursiveIterator
- SeekableIterator
- 異常
- 各種類及接口
- SplSubject
- SplObserver
- ArrayObject(將數組作為對象操作)
- SPL 函數
- 預定義接口
- Traversable(遍歷)接口
- Iterator(迭代器)接口
- IteratorAggregate(聚合式迭代器)接口
- ArrayAccess(數組式訪問)接口
- Serializable 序列化接口
- JsonSerializable
- Closure 匿名函數(閉包)類
- Generator生成器類
- 生成器(php5.5+)
- yield
- 反射
- 一、反射(reflection)類
- 二、Reflector 接口
- ReflectionClass 類報告了一個類的有關信息。
- ReflectionObject 類報告了一個對象(object)的相關信息。
- ReflectionFunctionAbstract
- ReflectionMethod 類報告了一個方法的有關信息
- ReflectionFunction 類報告了一個函數的有關信息。
- ReflectionParameter 獲取函數或方法參數的相關信息
- ReflectionProperty 類報告了類的屬性的相關信息。
- ReflectionClassConstant類報告有關類常量的信息。
- ReflectionZendExtension 類返回Zend擴展相關信息
- ReflectionExtension 報告了一個擴展(extension)的有關信息。
- 三、ReflectionGenerator類用于獲取生成器的信息
- 四、ReflectionType 類用于獲取函數、類方法的參數或者返回值的類型。
- 五、反射的應用場景
- phpRedis
- API
- API詳細
- redis DB 概念:
- 通用命令:rawCommand
- Connection
- Server
- List
- Set
- Zset
- Hash
- string
- Keys
- 事物
- 發布訂閱
- 流streams
- Geocoding 地理位置
- lua腳本
- Introspection 自我檢測
- biMap
- 原生
- php-redis 操作類 封裝
- redis 隊列解決秒殺解決超賣:
- swoole+框架筆記
- 安裝及常用Cli操作
- TCP
- 4種回調函數的寫法
- easyswoole
- 目錄結構
- 配置文件
- Linux+Nginx
- 前置
- linux
- 開源網站鏡像及修改yum源
- 下載linux
- Liunx中安裝PHP7.4 的三種方法(Centos8)
- yum安裝
- 源碼編譯安裝
- LNMP一鍵安裝
- 查看linux版本號
- 設置全局環境變量
- 查看php.ini必須存放的位置
- 防火墻與端口開放
- nohup 后臺運行命令
- linux 查看nginx,php-fpm運行用戶及用戶組
- 網絡配置
- CentOS中執行yum update時報錯
- 關閉防火墻
- 查看端口是否被占用
- 查看文件夾大小
- nginx相關
- 一個典型的nginx配置
- nginx關于多個項目的配置(易于管理)
- nginx.config配置文件的結構
- 1、events
- 2、http
- nginx的location配置詳解
- Nginx相關命令
- Nginx安裝
- 配置偽靜態
- 為靜態配置例子
- apache
- nginx
- pathinfo模式
- Shell腳本
- bash
- shell 語言中 0 代表 true,0 以外的值代表 false。
- 變量
- shell字符串
- shell數組
- shell注釋
- 向Shell腳內傳遞參數
- 運算符
- 顯示命令執行結果
- printf
- test 命令
- 流程控制與循環
- if
- case
- for
- while
- until
- break和continue
- select 結構
- shell函數
- shell函數的全局變量和局部變量
- 將shell輸出寫入文件中(輸出重定向)
- Shell腳本中調用另一個Shell腳本的三種方式
- 定時任務
- PHP實現定時任務的五種方法
- 優化
- ab壓力測試
- 緩存
- opcache
- memcache
- php操作
- 數據庫
- 配置
- 數據庫鎖機制
- 主從分布
- 數據庫設計
- 邏輯設計
- 物理設計
- 字段類型的選擇
- 筆記
- SET FOREIGN_KEY_CHECKS
- 字符集與亂碼
- SQL插入 去除重復記錄的實現
- 分區表
- nginx 主從配置
- nginx 負載均衡的配置
- 手動搭建Redis集群和MySQL主從同步(非Docker)
- Redis Cluster集群
- mysql主從同步
- 用安卓手機搭建 web 服務器
- 軟件選擇
- url重寫
- 大流量高并發解決方案
- 權限設計
- ACL
- RBAC
- RBAC0
- RBAC1(角色上下級分層)
- RBAC2(用戶角色限約束)
- RBAC3
- 例子
- Rbac.class.php
- Rbac2
- Auth.class.php
- fastadmin Auth
- tree1
- ABAC 基于屬性的訪問控制
- 總結:SAAS后臺權限設計案例分析
- casbin-權限管理框架
- 開始使用
- casbinAPI
- casbin管理API
- RBAC API
- Think-Casbin
- 單點登錄(SSO)
- OAuth授權
- OAuth 2.0 的四種方式
- 授權碼
- 隱藏式
- 密碼式
- 憑證式
- 更新令牌
- 例子:第三方登錄
- 微服務架構下的統一身份認證和授權
- 代碼審計
- 漏洞挖掘的思路
- 命令注入
- 代碼注入
- XSS 反射型漏洞
- XSS 存儲型漏洞
- xss過濾
- HTML Purifier文檔
- 開始
- id規則
- class規則
- 過濾分類
- Attr
- AutoFormat
- CSS
- Cache
- Core
- Filter
- html
- Output
- Test
- URI
- 其他
- 嵌入YouTube視頻
- 加快HTML凈化器的速度
- 字符集
- 定制
- Tidy
- URI過濾器
- 在線測試
- xss例子
- 本地包含與遠程包含
- sql注入
- 函數
- 注釋
- 步驟
- information_schema
- sql注入的分類
- 實戰
- 防御
- CSRF 跨站請求偽造
- 計動態函數執行與匿名函數執行
- unserialize反序列化漏洞
- 覆蓋變量漏洞
- 文件管理漏洞
- 文件上傳漏洞
- 跳過登錄
- URL編碼對照表
- XXE
- 前端、移動端
- html5
- meta標簽
- flex布局
- javascript
- jquery
- 選擇器
- 精細分類
- 事件
- on事件無效:
- jquery自定義事件
- 表單操作
- 通用
- select
- checkbox
- radio
- js正則相關
- js中判斷某字符串含有某字符出現的次數
- js匹配指定字符
- $.getjson方法配合在url上傳遞callback=?參數,實現跨域
- pajax入門
- jquery的extend插件制作
- jquery的兼容
- jquery的連續調用:
- $ 和 jQuery 及 $() 的區別
- 頁面響應順序及$(function(){})等使用
- 匿名函數:
- ajax
- 獲取js對象所有方法
- dom加載
- ES6函數寫法
- ES6中如何導入和導出模塊
- 數組的 交集 差集 補集 并集
- phantomjs
- js數組的map()方法操作json數組
- 實用函數
- js精確計算CalcEval 【價格計算】 浮點計算
- js精確計算2
- js數組與對象的遍歷
- bootstrap
- class速查
- 常見data屬性
- data-toggle與data-target的作用
- 組件
- bootstrapTable
- 表選項
- 表選項2
- 示例
- 數據格式(json)
- 用法(row:行,column:列)
- Bootstrap-table使用footerFormatter做統計列功能
- 示例2
- JQuery-Jquery的TreeGrid插件
- 服務器端分頁
- 合并單元格1
- 合并單元格2
- 合并單元格3
- 合并單元格4
- 合并單元格5(插件)
- 列求和
- 添加行,修改行、擴展行數據
- 擴展
- 開源項目
- PhpSpreadsheet
- 實例
- 會員 數據庫表設計
- 程序執行
- 開發總結
- API接口
- API接口設計
- json轉化
- app接口
- 雜項
- 三方插件庫
- 檢測移動設備(包括平板電腦)
- curl封裝
- Websocket
- 與谷歌瀏覽器交互
- Crontab管理器
- 實用小函數
- PHP操作Excel
- SSL證書
- sublime Emmet的快捷語法
- 免費翻譯接口
- 接口封裝
- 免費空間
- 架構師必須知道的26項PHP安全實踐
- 大佬博客
- 個人支付平臺
- RPC(遠程調用)及框架