核心要點
PHP允許使用多字節變量名(例如$a∩b
、$Ʃxy
和$Δx
),mbstring
和其他擴展程序可處理Unicode字符串,utf8_encode()
和utf8_decode()
函數可在UTF -8和ISO-8859-1編碼之間轉換字符串。然而,人們普遍認為PHP缺乏Unicode支持。本文介紹了缺乏Unicode支持的含義,並演示瞭如何使用一個為PHP應用程序帶來Unicode支持的庫——Portable UTF-8。
PHP中的Unicode支持
PHP缺乏Unicode/多字節支持意味著標準字符串處理函數將字符串視為單字節字符序列。事實上,PHP官方手冊將PHP中的字符串定義為“一系列字符,其中一個字符與一個字節相同”。 PHP僅支持8位字符,而Unicode(以及許多其他字符集)可能需要多個字節來表示一個字符。 PHP的這一限制幾乎影響字符串操作的各個方面,包括(但不限於)子字符串提取、確定字符串長度、字符串分割、混排等。解決這個問題的努力始於2005年初,但在2010年,由於多種原因,將原生Unicode支持引入PHP的工作被停止並擱置。由於PHP中的原生Unicode支持可能需要數年時間才能實現(如果真的會實現的話),開發人員必須依賴可用的mbstring
和iconv
等擴展來填補這一空白,但這些擴展只提供有限的Unicode支持。這些庫並非以Unicode為中心,也能夠在非Unicode編碼之間進行轉換。它們為簡化Unicode字符串處理做出了積極貢獻。但是,上述擴展也有一些缺點。它們僅提供有限的Unicode字符串處理功能,並且沒有一個默認啟用。服務器管理員必須顯式啟用任何一個或所有擴展才能通過PHP應用程序訪問它們。共享主機提供商通常會通過安裝一兩個擴展來使情況變得更糟,這使得開發人員難以依靠始終可用的API來滿足其Unicode需求。儘管如此,好消息是PHP可以輸出Unicode文本。這是因為PHP並不真正關心我們是否正在發送以ASCII編碼的英文文本或屬於其字符以多個字節編碼的語言的其他文本。了解這一點後,PHP開發人員現在只需要一個提供舒適的基於Unicode的字符串操作的API。
Portable UTF-8
最近的解決方案是創建用PHP編寫的用戶空間庫。即使服務器/語言級別缺少支持,這些庫也可以輕鬆地與應用程序捆綁在一起,以確保Unicode支持的存在。許多開源應用程序已經包含了自己的此類庫,還有更多應用程序使用免費提供的第三方庫;Portable UTF-8就是這樣一個庫。 Portable UTF-8是一個免費的輕量級庫,構建在mbstring
和iconv
之上。它擴展了這兩個擴展的功能,提供了大約60個基於Unicode的字符串操作、測試和驗證函數;它為幾乎所有PHP的常用字符串處理函數提供了UTF-8感知的對應函數。顧名思義,Portable UTF-8使用UTF-8作為其主要字符編碼方案。該庫出於速度原因而使用可用的擴展(mbstring
和iconv
),並彌合了直接使用它們時的一些不一致之處,但如果服務器上沒有這些擴展,則會回退到用純PHP編寫的UTF-8例程。 Portable-UT8完全可移植,可與任何PHP 4.2或更高版本的安裝一起使用。
使用Portable UTF-8進行字符串處理
具有較差Unicode支持的文本編輯器在讀取文本時可能會損壞文本,從這樣的編輯器複製並粘貼到Web表單中的文本可能是應用程序無效UTF-8的來源。在處理用戶提交的輸入時,務必確保輸入完全符合應用程序的預期。要檢測文本是否為有效的UTF-8,可以使用庫的is_utf8()
函數。
if (is_utf8($_POST['title'])) { // 执行某些操作... }
從無效字節中恢復字符是不可能的,因此去除無法識別為有效UTF-8字符的字節可能是您的唯一選擇。可以使用utf8_clean()
函數去除無效字節。
$title = utf8_clean($_POST['title']);
每個Unicode字符都可以編碼為相應的HTML實體,您可能希望以這種方式編碼文本以幫助防止XSS攻擊,然後再將其輸出到瀏覽器。
echo utf8_html_encode($title);
通常會在字符串的開頭和結尾修剪空格。 Unicode列出了大約20個空格字符,還有一些基於ASCII的控製字符也應被視為需要修剪的對象。
$title = utf8_trim($title);
另一方面,字符串中間可能存在此類空格的重複項,應將其刪除。以下顯示瞭如何將utf8_remove_duplicates()
和utf8_ws()
組合使用:
$title = utf8_remove_duplicates($title, utf8_ws());
用於創建URL片段以實現SEO目的的傳統解決方案使用音譯並從片段中去除所有非ASCII字符。這使得URL的價值低於其本來的價值。雖然URL可以支持UTF-8編碼的字符,但無需進行此類去除或音譯,我們可以創建包含任何語言字符的豐富片段:
$slug = utf8_url_slug($title, 30); // 字符长度30
從輸入驗證開始到將數據保存到某個數據庫,支持Unicode的應用程序關注的是字符和字符長度,而不是字節和字節長度。這種關注點的轉變需要一個理解這種差異的新接口。通常需要對輸入字符長度進行限制,因此,如果輸入超過60個字符的長度,我們將創建一個子字符串。
if (utf8_strlen($title) > 60) { $title = utf8_substr($title, 0, 60); }
或者:
if (!utf8_fits_inside($title , 60)) { $title = utf8_substr($title, 0 ,60); }
使用Portable-UT8庫有三種不同的方法可以訪問單個字符。我們可以使用utf8_access()
來訪問單個字符。
echo '第六个字符是:' . utf8_access($string, 5);
utf8_chr_map()
允許使用回調函數迭代地訪問單個字符。
utf8_chr_map('some_callback', $string);
我們可以使用utf8_split()
將字符串拆分為字符數組,並將數組元素作為單個字符進行處理。
array_map('some_callback', utf8_split($string));
處理Unicode可能還需要我們查找字符串中的最小/最大代碼點、分割字符串、處理字節順序標記、字符串大小寫轉換、隨機化/混排、替換等。所有這些都受Portable-UT8支持。
結論
PHP 6的開發已被停止,導致長期需要的原生Unicode支持被推遲,這對於開發多語言應用程序至關重要。因此,在此期間,服務器端擴展和用戶空間庫(如Portable UTF-8)在幫助開發人員創建更好的標準化Web,以滿足本地需求方面發揮著重要作用。
(由於篇幅限制,此處省略了FAQs部分)
以上是使用便攜式UTF-8將Unicode帶到PHP的詳細內容。更多資訊請關注PHP中文網其他相關文章!