首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 中文字串截取完整指南:mb_substr、mb_strcut 與自定義函數對比

     編輯:PHP 綜合知識

前言

PHP 內建 substr() 按位元組截取,對多位元組編碼(UTF-8 中文佔 3 位元組)會產生「半個字元」導致亂碼。本文系統梳理三種解決方案:mbstring 擴展函數、自定義位元組檢測函數、輸出端截斷技巧,並對比 mb_substr 與 mb_strcut 的本質差異。

方案一:mbstring 擴展(推薦、標準、高效)

環境需求

確認 php.ini 已啟用 extension=mbstring,並設定 mbstring.internal_encoding = UTF-8。

核心函數對比

函數單位行為適用場景
mb_substr($str, $start, $len, 'UTF-8')字元按 Unicode 字元截取,不會產生半字元顯示摘要、標題截斷、長度統計
mb_strcut($str, $start, $len, 'UTF-8')位元組按位元組截取,但會自動避開半字元(截到完整字元為止)需嚴格控制位元組長度(如資料庫 VARCHAR 長度)

實例演示

$str = '這樣一來我的字符串就不會有亂碼^_^';

echo mb_substr($str, 0, 7, 'UTF-8'); // 輸出:這樣一來我的字(7 個字元)
echo mb_strcut($str, 0, 7, 'UTF-8'); // 輸出:這樣一(約 7 位元組,截在完整字元邊界)

方案二:無 mbstring 環境的自定義函數

原理:遍歷字串,檢測 ord($char) > 127 判斷是否為多位元組字元首位元組(UTF-8 首位元組最高位為 1),若是則一次取 2~4 位元組(視編碼而定,簡體中文常見 3 位元組,此處簡化為 2 位元組示意)。

/**
 * 純 PHP 實現中英混排字串截取(UTF-8)
 * @param string $str 來源字串
 * @param int $len 目標字元數(中英各算 1)
 * @param string $suffix 截斷後綴
 * @return string
 */
function substr_utf8_mixed($str, $len, $suffix = '...') {
    $result = '';
    $count = 0;
    $bytes = strlen($str);
    for ($i = 0; $i < $bytes && $count < $len; $i++) {
        $char = $str[$i];
        $ord = ord($char);
        if ($ord < 128) { // ASCII
            $result .= $char;
            $count++;
        } elseif (($ord & 0xE0) === 0xC0) { // 2-byte sequence
            $result .= $str[$i] . $str[$i+1];
            $i++; $count++;
        } elseif (($ord & 0xF0) === 0xE0) { // 3-byte sequence (中文常見)
            $result .= $str[$i] . $str[$i+1] . $str[$i+2];
            $i += 2; $count++;
        } elseif (($ord & 0xF8) === 0xF0) { // 4-byte sequence (Emoji 等)
            $result .= $str[$i] . $str[$i+1] . $str[$i+2] . $str[$i+3];
            $i += 3; $count++;
        }
    }
    return ($count < mb_strlen($str, 'UTF-8')) ? $result . $suffix : $result;
}

// 測試
$str = "34中華人民共和國56";
echo substr_utf8_mixed($str, 3); // 輸出:34中...

優點:無擴展依賴。缺點:效能較低、需自行處理邊界與錯誤編碼。

方案三:輸出端技巧(僅限顯示截斷)

// 利用 chr(0) 截斷輸出緩衝,瀏覽器不會顯示後續內容
echo substr($str, 0, 30) . chr(0);

此法不改變字串本身,僅影響輸出,不建議用於資料處理或存儲。

效能與選型建議

  1. 生產環境首選 mbstring:C 層實現、效能高、功能全(mb_strlen、mb_strpos、mb_strtolower 等)。
  2. 受限環境用自定義函數:封裝為工具類,加入快取機制緩解效能壓力。
  3. 資料庫層面:定義欄位為 VARCHAR(255) CHARACTER SET utf8mb4,按字元長度限制,避免應用層截取。
  4. 前端配合:CSS text-overflow: ellipsis 處理單行截斷,複雜場景用 JS 處理。

常見坑點提醒

  • mb_substr($str, 0, 10) 若省略 encoding 參數,預設使用 mbstring.internal_encoding,若未設定則回退到 ISO-8859-1 導致錯誤 → 建議顯式傳遞 'UTF-8'。
  • Emoji(😀)佔 4 位元組,mb_substr 正確視為 1 字元,自定義函數需支援 4-byte 序列。
  • strlen() 回傳位元組數,mb_strlen() 回傳字元數,勿混淆。

總結

中文字串截取的核心是字元邊界識別。現代 PHP 專案請務必啟用 mbstring 並統一使用 mb_substr() / mb_strlen() 等函數族;舊環境或嵌入式場景可採用自定義函數並加強測試。切記:資料層面按字元存儲,展示層面按視覺截斷,分層處理最穩健。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved