在 PHP 開發中,字符串截取看似簡單,但一旦涉及中文、日文或其他多位元組編碼,直接使用 substr 往往會導致亂碼或截斷錯誤。本文分享一個健壯的 msubstr 函數,支援 UTF-8、GB2312、GBK、Big5 等主流編碼,並可自訂起始位置、長度與尾碼,是處理多語言內容截斷的得力工具。
PHP 內建的 substr 按位元組操作,對於 UTF-8 編碼的中文(佔 3 位元組)會將一個字符強行拆分,產生無效字符。雖然 mb_substr 解決了大多數情況,但某些伺服器環境未安裝 mbstring 擴展,此時需要備用方案(如 iconv_substr 或正則匹配)。
/**
* 字符串截取,支援中文和其他編碼
* @param string $str 待截取字符串
* @param int $start 起始位置(從 0 開始)
* @param int $length 截取長度
* @param string $charset 編碼格式,預設 utf-8
* @param bool|string $suffix 截斷後綴,true 為 '...',字符串則用該字符串,false 不加後綴
* @return string
*/
function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true) {
if (function_exists("mb_substr")) {
$slice = mb_substr($str, $start, $length, $charset);
} elseif (function_exists('iconv_substr')) {
$slice = iconv_substr($str, $start, $length, $charset);
if (false === $slice) $slice = '';
} else {
// 純 PHP 正則備用方案
$re = [
'utf-8' => "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/",
'gb2312' => "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/",
'gbk' => "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/",
'big5' => "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/"
];
preg_match_all($re[$charset], $str, $match);
$slice = join("", array_slice($match[0], $start, $length));
}
return $suffix ? $slice . '...' : $slice;
}
$str = "你好,世界!Hello World";
// UTF-8 環境
echo msubstr($str, 0, 6); // 輸出:你好,世界...
echo msubstr($str, 3, 4, 'utf-8', '>>'); // 輸出:世界>>
// GBK 編碼字符串(需確保檔案編碼為 GBK)
$gbkStr = iconv('UTF-8', 'GBK', $str);
echo msubstr($gbkStr, 0, 4, 'gbk'); // 正確截取前 4 個中文字符
false 時需處理為空字符串。...,可自訂或關閉。將此函數放入通用工具庫,即可在專案任何地方安心截取多語言字符串,告別亂碼煩惱。