測試代碼
<?php
$str = '123456歡迎大家的光臨';
echo 'substr: ' . substr($str, 0, 4) . PHP_EOL; // 1234
echo 'iconv_substr: ' . iconv_substr($str, 0, 4, 'UTF-8') . PHP_EOL; // 1234歡
echo 'mb_substr: ' . mb_substr($str, 0, 4, 'UTF-8') . PHP_EOL; // 1234歡
核心差異
| 函數 | 單位 | 多字節支援 | 依賴擴展 | 效能 |
substr | 字節 | ❌ 截取中文會亂碼 | 核心內建 | 最快 |
iconv_substr | 字符 | ✅ 需指定編碼 | iconv(部分系統需 GNU libiconv) | 較慢(先轉碼再截取) |
mb_substr | 字符 | ✅ 原生多字節安全截取 | mbstring(標準安裝通常啟用) | 快(直接按編碼截取) |
選型建議
- 首選
mb_substr:兼容性最好、效能最高、API 直觀。
iconv_substr 作為備選:僅在 mbstring 不可用時考慮。
- 純 ASCII/英文場景可用
substr 追求極致效能。
最佳實踐:封裝統一函數
function mbs($str, $start, $length = null, $encoding = 'UTF-8') {
if ($length === null) $length = mb_strlen($str, $encoding);
return mb_substr($str, $start, $length, $encoding);
}
// 使用
echo mbs('你好世界', 0, 2); // 你好
常見陷阱
mbstring.internal_encoding 未設定導致預設編碼不一致,建議在 php.ini 或入口文件設 mb_internal_encoding('UTF-8')。
iconv_substr 在某些舊版 Linux(如 CentOS 6)上因 glibc 版本導致錯誤截取。
- 截取長度超出字符串實際長度時,
mb_substr 返回剩餘部分,不報錯。