1. 程式人生 > >PHP中文亂碼的三個原因及解決方法

PHP中文亂碼的三個原因及解決方法

我們在做PHP專案的時候,經常會遇到中文亂碼的問題,有時候編碼問題還導致MYSQL的報錯。中文亂碼總共有三個原因

1:APACHE伺服器設定導致亂碼

2:PHP,或者HTML頁面編碼導致中文亂碼

3:MYSQL資料庫的表以及欄位編碼導致中文亂碼

我們分別從這三個部分來探究PHP程式設計中的編碼問題

在這之前我們要了解一些基本理論:

1、檔案編碼

每個檔案在儲存的時候都可以選擇以什麼編碼儲存,例如用WINDOWS的記事本建立一個檔案可以選擇ANSI 以及UTF8等等編碼。我們選擇了什麼編碼該檔案就以這種編碼方式儲存在硬碟上。 讀取該檔案資料的時候也會指定一種編碼來開啟,如果指定的編碼與檔案儲存的時候的編碼不一樣的話就會出現亂碼

2、HTML的編碼

在網頁頭部一般有這樣一個<HEAD>區域

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />
這個的意思是讓客戶端知道,接下來輸出的是html程式碼(text/html),並且以下輸出的內容都將是utf-8編碼的。如果我們用記事本建立一個HTML檔案 該檔案包含

<meta http-equiv=”Content-Type” content=”text/html; charset=utf-8″ />

但是在儲存的時候卻以ANSI編碼格式儲存,那麼我們用瀏覽器開啟這個檔案時,瀏覽器看見META 行的UTF8編碼設定後 就將檔案以UTF8格式輸出,而檔案本來是ANSI編碼,這樣便出現了中文亂碼。

一:APACHE伺服器編碼

在APACHE配置檔案中有一行是編碼的設定 預設的是AddDefaultCharset ISO-8859-1,大部分人認為應該將這句改為 AddDefaultCharset UTF-8 。而蝸牛認為這是誤人子弟。 這項配置是告訴APACHE伺服器選用什麼樣的編碼來輸出WEB頁面(這樣做會忽略,HTML頁面中的頁面編碼的設定 EG:<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″ />),如果我們建立一個GB2312的頁面就會出現中文亂碼 。所以最好的方法是將AddDefaultCharset ISO-8859-1這一項註釋掉 #AddDefaultCharset

二:PHP編碼問題

php最終生成的是文字檔案,而他要從資料庫中取出文字資料,還要把文字資料寫到資料庫中。由於MYSQL並不知道PHP傳送給他的是什麼編碼的資料,所以需要客戶端PHP告訴他存取的是什麼編碼的資料。然後MYSQL會自動將PHP傳送來的資料轉換成目標編碼格式的資料。

比如: PHP要將 文字資料DATE 寫入到資料庫欄位field中,PHP傳送的是UTF-8編碼的資料,而DATE是以GB2312方式儲存的。這時候PHP通過設定告訴MYSQL 我發的是UTF-8格式,MYSQL接到資料後 說:”我知道了,來誰專門負責將UTF-8轉換成GB2312“ 於是MYSQL中的一個專門負責此事的小兵跑來 把資料拿走經過加工放到指定位置,如果PHP誤將UTF-8編碼的資料 當作GB2312編碼 送給MYSQL的時候,MYSQL會叫上次那個負責UTF-8—-GB2312的小兵來負責,而小兵不管三七二十一按同樣方法轉換存起來,這就出現了錯誤,亂碼就產生了。取資料的時候也一樣,PHP要告訴MYSQL要取出什麼樣編碼的資料。

PHP通過character_set_client告訴MYSQL,php存入資料庫的是什麼編碼方式

PHP通過character_set_results告訴MYSQL,php需要取什麼樣編碼的資料

PHP通過character_set_connection告訴MYSQL,PHP查詢中的文字,使用什麼編碼

就算上面的大家都注意了,還有個問題也可能導致亂碼。那就是PHP檔案(生成的HTML頁面)本身的編碼問題

如果MYSQL傳來的資料 編碼與PHP本身編碼不一致也會導致亂碼

三:MYSQL編碼問題

Mysql目前支援多字符集,並且,支援在不同的字符集之間轉換(便於移植和支援多語言)。
Mysql可以設定伺服器級字符集、資料庫級字符集、資料表級字符集、表列的字符集,實際上,最終使用字符集的地方是儲存字元的列,比如,你設定 table1中col1列是字元型別,col1才用到了字符集,如果table1表的col2列是int型別,col2不使用字符集的概念。
伺服器級字符集、資料庫級字符集、資料表級字符集都是為列的字符集做預設選項的。
Mysql一定有一個字符集,可以通過啟動時加引數指定 ,也可以編譯時指定,也可以在配置檔案裡指定。Mysql伺服器字符集,只是做為資料庫級的預設值。建立資料庫時,你可以指定字符集,如果沒指定,就使用伺服器的字符集。同理,建立表時,你可以指定表級的字符集,如果沒指定,使用資料庫的字符集做為表的字符集。建立列時,你可以指定某列的字符集,如果沒指定,就使用表的字符集。
通常情況下,您只需設定伺服器級的字符集,其它的資料庫級,表級,以及列級的字符集,都繼承自伺服器級字符集。
由於UTF8是最廣的字符集,所以,一般情況下,我們設定Mysql伺服器級的字符集為UTF8!

總結:

要保證不亂碼,需將三個編碼統一:

一:是網頁自身的編碼

二:是HTML裡指定的編碼

三:是PHP告訴Mysql的編碼(包括character_set_client和character_set_results)。

第一和第二個編碼,如果使用DW之類的編輯器寫的網頁,通常是一致的,但用記事本寫的網頁,有可能不一致。
第三個編碼,需要手工通知Mysql。這步可以通過在PHP裡使用mysql_query(“set names characterX”)來實現。