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

PHP mb_substr 完美截取中文字符串不亂碼

     編輯:PHP 相關知識

PHP substr() 按字節截取,多字節編碼 (UTF-8/GBK) 中文會導致亂碼。mb_substr() 支持指定編碼按字符截取,是處理中文截斷的標準方案。

基本語法

mb_substr(string $string, int $start, int $length = null, string $encoding = mb_internal_encoding()) : string

編碼指定示例

GBK 編碼

<?php
$str = '我是誰'; // GBK 編碼文件
echo mb_substr($str, 0, 1, 'gbk'); // 輸出: 我
echo mb_substr($str, 1, 2, 'gbk'); // 輸出: 是誰

UTF-8 編碼

<?php
$str = '我abc是誰'; // UTF-8 編碼文件
echo mb_substr($str, 0, 2, 'utf-8'); // 輸出: 我a
echo mb_substr($str, 2, 3, 'utf-8'); // 輸出: bc是

中英混合無縫支持,按「字符」而非「字節」計算長度。

封裝通用截取函數

<?php
/**
 * 多編碼安全截取
 * @param string $str
 * @param int $start
 * @param int $length
 * @param string $charset 自動檢測優先級: utf-8, gbk, gb2312, big5
 * @param string $suffix 截斷後綴
 * @return string
 */
function msubstr($str, $start = 0, $length, $charset = 'auto', $suffix = '...') {
    if ($charset === 'auto') {
        $charset = detectEncoding($str);
    }
    
    if (mb_strlen($str, $charset) <= $length) {
        return $str;
    }
    
    return mb_substr($str, $start, $length, $charset) . $suffix;
}

/**
 * 簡易編碼檢測
 */
function detectEncoding($str) {
    $encodings = ['utf-8', 'gbk', 'gb2312', 'big5'];
    foreach ($encodings as $enc) {
        if (mb_check_encoding($str, $enc)) {
            return $enc;
        }
    }
    return 'utf-8'; // 默認
}

// 使用
echo msubstr('你好世界', 0, 2); // 你好...
echo msubstr('Hello世界', 0, 5); // Hello...

常見陷阱與解決

1. 文件編碼與聲明不一致

<?php
// 文件保存為 UTF-8,但代碼寫 'gbk'
$str = '中文'; // 實際是 UTF-8 字節
echo mb_substr($str, 0, 1, 'gbk'); // 亂碼或錯誤

// 解決:統一項目編碼為 UTF-8,代碼中統一用 'utf-8'
declare(encoding='UTF-8'); // PHP 5.3+ 聲明腳本編碼

2. mbstring 擴展未安裝

# Ubuntu
sudo apt-get install php-mbstring
# CentOS
sudo yum install php-mbstring
# Windows php.ini 取消註釋
extension=mbstring

3. 數據庫連接編碼不匹配

<?php
// MySQLi
$mysqli->set_charset('utf8mb4'); // 推薦 utf8mb4 支持 emoji

// PDO
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8mb4', $user, $pass);
// 確保讀出字符串編碼與 mb_substr 參數一致

性能對比

<?php
$str = str_repeat('中文', 10000);
$iterations = 1000;

$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) substr($str, 0, 10);
echo "substr: " . (microtime(true) - $start) . "s\n";

$start = microtime(true);
for ($i = 0; $i < $iterations; $i++) mb_substr($str, 0, 10, 'utf-8');
echo "mb_substr: " . (microtime(true) - $start) . "s\n";

/* 輸出示例:
substr: 0.0012s
mb_substr: 0.0085s (約 7x 慢,但正確)
*/

正確性優先,性能差異在業務邏輯中通常可忽略。

現代替代:grapheme_substr (PHP 5.6+ intl 擴展)

<?php
// 按「用戶感知字符」(書寫字素簇) 截取,正確處理 emoji、組合字符
$str = '👨‍👩‍👧‍👦家庭'; // 1個 emoji 序列 + 2個漢字
echo mb_substr($str, 0, 1, 'utf-8'); // 可能截斷 emoji
echo grapheme_substr($str, 0, 1);    // 完整截取 👨‍👩‍👧‍👦

涉及 emoji、複雜文字系統時,grapheme_* 系列函數更準確。

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