核心差異
| 函數 | 單位 | 中文處理 | 需擴展 | 典型用途 |
strlen() | 位元組 | UTF-8 佔 3 位元組 | 核心內建 | 二進位資料、原始位元組長度 |
mb_strlen() | 字元 | 依編碼正確計為 1 | mbstring | 顯示長度、截斷、驗證 |
實測對比 (檔案編碼 UTF-8)
<?php
$str = '中文a字1符'; // 4 中文 + 2 ASCII = 6 字元
echo strlen($str); // 14 (4*3 + 2*1)
echo mb_strlen($str, 'UTF-8'); // 6
echo mb_strlen($str, 'GBK'); // 8 (中文 2 bytes)
echo mb_strlen($str, 'GB2312'); // 10 (部分字元擴展)
判斷是否載入 mbstring
<?php
if (!extension_loaded('mbstring')) {
die('請在 php.ini 啟用 extension=mbstring');
}
echo mb_internal_encoding(); // 目前內部編碼
中英混排「顯示寬度」計算 (全形=2, 半形=1)
<?php
/**
* 計算字串顯示寬度 (適用於終端機對齊、固定寬度排版)
*/
function strWidth(string $str, string $encoding = 'UTF-8'): int {
$len = mb_strlen($str, $encoding);
$bytes = strlen($str);
// 近似公式:總位元組 - 字元數 = 多佔的位元組數 (UTF-8 中文多 2 bytes)
// 寬度 = ASCII數 + 中文數*2 = (字元數 - 中文數) + 中文數*2 = 字元數 + 中文數
// 中文數 ≈ (bytes - 字元數) / 2
$chineseCount = (int)(($bytes - $len) / 2);
return $len + $chineseCount;
}
echo strWidth('中文a字1符'); // 10 (4*2 + 2*1)
mb_substr 安全截取
<?php
$str = '中文English測試';
// 錯誤:substr($str, 0, 6) -> '中文Eng' (截斷多位元組)
// 正確:
echo mb_substr($str, 0, 6, 'UTF-8'); // '中文Engl' (6 字元)
echo mb_substr($str, 0, 10, 'UTF-8'); // '中文English測'
常見編碼對照
| 編碼 | 中文位元組 | mb_strlen 參數 |
| UTF-8 | 3 | 'UTF-8' |
| GBK / CP936 | 2 | 'GBK' |
| GB2312 | 2 | 'GB2312' |
| BIG-5 | 2 | 'BIG-5' |
最佳實踐清單
- 專案統一 UTF-8 (資料庫、PHP、HTML、JS)。
- 所有字串長度、截取、比較操作全面改用 mb_* 函數。
- 在
php.ini 設定 mbstring.internal_encoding = UTF-8、mbstring.http_input = UTF-8、mbstring.http_output = UTF-8。
- 框架通常已封裝
str::length()、str::substr(),優先使用框架工具類。
- 資料庫欄位長度
VARCHAR(255) 是字元數而非位元組 (MySQL 4.1+),但儲存體按位元組計算。