技巧文章:UTF8下的中文PHP編程

來源:互聯網
上載者:User

前言:

說實話,
涼鞋也覺得 UTF8 是好東西……
畢竟同屏顯示中日韓對東亞人的吸引力是不小的……
(當然好處不僅是這點啦……)
不僅是網頁程式……
很多應用程式的核心都開始使用 Unicode 編碼……
目的是顯而易見的:支援多語言顯示……
微軟的所有軟體都是 Unicode 核心……
所以日文軟體拿到你的中文 XP 上是可以正常顯示的……
而中文 98 就會因為 GB 核心安裝其他語言軟體時造成亂碼……

至於 UTF8 ,
可以說是 Unicode 的一個分支,
它用三個位元組儲存一個漢字……
(Unicode 用四個位元組)
應用軟體都集體投奔 Unicode 了……
就不允許我們搞網頁程式的用 UTF8?

本文中涼鞋就盡量多方位介紹一下 UTF8 編碼下的 PHP 編程……
至於為什麼單獨介紹“中文”……
一來是因為英文這玩意實在不需要考慮 UTF8 ……
除非你準備做多語言系統……
(我要發些牢騷:現在的老外寫程式時根本不重視這個問題……)
二來是中日韓等多位元組語系在 UTF8 編碼下的處理方式其實大同小異……
依葫蘆畫瓢即可……
好……先從資料庫處理部分開始吧……


==========================================
串連資料庫

很多人剛升級到 Mysql 4.1 時會探索資料亂掉了……
其實是因為 Mysql 從 4.1 開始支援字元集了……
而且預設字元集正是 UTF8 ……
(充分證明與國際接軌的重要性…… 嘿嘿……)
而以前我們大多使用 utf8 或是 GBK 編碼……
這樣以來輸出的資料當然是亂碼……
要解決亂碼……
就得讓程式知道該擷取什麼編碼的資料……

我們假設你以前的資料庫是 utf8 編碼的……
那麼你可以在查詢前添加一句

mysql_query('SET CHARACTER SET utf8') or die("Query failed : " . mysql_error());
當然,由於 4.1 以上才需要這樣處理,
因此我們可以加上判斷:

$mysqlversion = $db->query_first("SELECT VERSION() AS version");
if ($mysqlversion['version'] >= '4.1')
{
mysql_query('SET CHARACTER SET utf8') or die("Query failed : " . mysql_error());
}
這樣以來不管 Mysql 預設編碼是什麼都可以正常存取了……
(不論您是存活期,還是存定期,甚至是零存整取都沒有問題鳥……)

但是,人家都國際化鳥……
您還在用 utf8 行嗎?
如何轉碼呢?
還有……
資料升級時出現亂碼怎麼辦?
涼拌!
且聽下回分解……

============================================
資料升級至 4.1

要升級……
就得先匯出……
要說老外還真不負責……
以前的匯出方式總是弄丟一些中文字元……
比如把“我愛你娘”弄成“我愛你”啦……
(通常是丟失一段資料最末尾的字)
整個兒差了一輩兒……
(用石榴姐的話說就是“這麼大逆不道的事實在是太刺激了”……)
為了保護您脆弱的心臟……
也為了維護中國傳統倫理道義……
您可以把資料包含中文字元的欄位改為二進位(Binary)編碼……
具體方法嘛……
可以運行這個語句:

ALTER TABLE `表名` CONVERT TO CHARACTER SET binary;
這樣,那些字元類型欄位,如:
CHAR、VARCHAR 和 TEXT
將轉換為
BINARY、VARBINARY 和 BLOB
然後再匯出並匯入到 4.1 環境中……
當然,最後一項繁瑣的工作是:
你需要把它們的類型再改回來……

有往 4.1 升級的……
當然也有往下降級的……
怎麼降級???
涼鞋去上個廁所……
而您請翻下頁……

=============================================
資料從 4.1 降級

有人發現從4.1匯出的 SQL 檔案無法匯入低版本程式……
問題其實很簡單……
而且 Mysql 已經為我們想好了一切……
匯出時請添加 –compatible 參數……
我們假設您的資料庫是 utf8 編碼的……
而且目標資料庫版本為 4.0 ……
那麼命令列下這麼寫:

shell>mysqldump --user=username --password=password --compatible=mysql40 --default-character-set=utf8 database > db.sql
這樣匯出的 SQL 檔案就能夠順利匯入低版本資料庫了……

資料庫部分算是搞定了……
但 PHP 編程方面要如何注意呢?
還得勞您翻下頁……
http://www.knowsky.com
=============================================
PHP 檔案編碼

是否所有 PHP 檔案都必須轉成 UTF8 編碼呢?
涼鞋告訴您是 NO ……

這麼說吧……
如果檔案中包含需要顯示出來的中文字元……
就應該轉為 UTF8 編碼……
舉例子吧:

// 我是涼鞋
echo time();
上面的代碼雖有代碼……
但是由於存在於注釋中……
不會輸出……
所以這個頁面可以不用轉換為 UTF8 格式……

再如:

echo "我是涼鞋";
這個明顯有中文字元輸出……
您還是老老實實轉換為 UTF8 吧……

當然現在很多程式都採用模板(語言套件)技術……
程式(非語言套件檔案)裡是看不到任何供輸出的字元的……
這樣以來我們只需要將語言套件檔案轉成 UTF8 編碼即可……
(語言套件的優勢就在這裡啊…… 啊哈哈哈哈哈……)
'http://www.knowsky.com
==================================================

UTF8 中文截取

由於 UTF8 使用三個位元組……
所以傳統的 substr 函數就沒轍了……
很多高手都寫了 UTF8 中文字元截取函數……
這裡送上幾種:

1.先算再取

/**
* Author : Dummy | Zandy
* Email : lianxiwoo@gmail.com | hotmail.com
* Create : 200512
* Usage : echo join('', String::subString_UTF8('漢字', 0, 1));
*/
ini_set('display_errors', 1);
error_reporting(E_ALL ^ E_NOTICE);
class String {
function subString_UTF8($str, $start, $lenth)
{
$len = strlen($str);
$r = array();
$n = 0;
$m = 0;
for($i = 0; $i < $len; $i++) {
$x = substr($str, $i, 1);
$a = base_convert(ord($x), 10, 2);
$a = substr('00000000'.$a, -8);
if ($n < $start){
if (substr($a, 0, 1) == 0) {
}elseif (substr($a, 0, 3) == 110) {
$i += 1;
}elseif (substr($a, 0, 4) == 1110) {
$i += 2;
}
$n++;
}else{
if (substr($a, 0, 1) == 0) {
$r[] = substr($str, $i, 1);
}elseif (substr($a, 0, 3) == 110) {
$r[] = substr($str, $i, 2);
$i += 1;
}elseif (substr($a, 0, 4) == 1110) {
$r[] = substr($str, $i, 3);
$i += 2;
}else{
$r[] = '';
}
if (++$m >= $lenth){
break;
}
}
}
return $r;
} // End subString_UTF8
}// End String
echo join('', String::subString_UTF8('漢字', 0, 1));
2.先截後取
這種方式涼鞋覺得很巧妙……
用傳統截取函數先截斷……
然後判斷中文單個字元是否被分割開……
如果是……則處理之……
要特別注意的是 substr 函數的第三個參數必須大於 3 ……
至於為什麼不用涼鞋解釋了吧?

// A trim function to remove the last character of a utf-8 string
// by following instructions on http://en.wikipedia.org/wiki/UTF-8
// dotann
// usage: $str = utf8_trim(substr($str,0,50));
function utf8_trim($str) {
$len = strlen($str);
for ($i=strlen($str)-1; $i>=0; $i-=1){
$hex .= ' '.ord($str[$i]);
$ch = ord($str[$i]);
if (($ch & 128)==0) return(substr($str,0,$i));
if (($ch & 192)==192) return(substr($str,0,$i));
}
return($str.$hex);
}
$str = '漢字';
echo utf8_trim(substr($str,0,3));
3.還有其它方法,
比如 007pig 為我們 vBulletin 中文版裡所寫的函數……
短小精悍……
源碼不便放出……
對不住鳥……



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。