PHP 內建 substr() 僅支援單位元組字元(英文、數字),處理中文等多位元組字元會產生亂碼。本文詳細說明 substr() 用法,並提供支援 UTF-8 中英混排的完整解決方案。
<?php
$str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
echo "原字串:{$str}
";
echo "從第5個開始:".substr($str, 5)."
"; // FGHIJ...
echo "第9個起取4個:".substr($str, 9, 4)."
"; // JKLM
echo "倒數5個:".substr($str, -5)."
"; // VWXYZ
echo "倒數8起取4個:".substr($str, -8, 4)."
"; // STUV
echo "倒數8到倒數2:".substr($str, -8, -2)."
"; // STUVWXY
<?php
$str = "你好世界";
echo substr($str, 0, 3); // 輸出 "你" (亂碼)
/* 原因:UTF-8 中文佔 3 位元組,substr 按位元組截取,切在字元中間 */
<?php
$str = "你好世界,Hello World";
// 確保已啟用 mbstring 擴充套件
echo mb_substr($str, 0, 4, 'UTF-8'); // "你好世"
echo mb_substr($str, 4, 6, 'UTF-8'); // "界,Hello"
echo mb_substr($str, -6, null, 'UTF-8'); // "World"
優點:原生支援多位元組編碼、效能較好、語法與 substr 一致。
<?php
function utf8_substr($str, $start, $length = null, $suffix = '...') {
// 將 UTF-8 字串轉為字元陣列
preg_match_all('/./u', $str, $matches);
$chars = $matches[0];
$total = count($chars);
if ($start < 0) $start = $total + $start;
if ($start < 0) $start = 0;
if ($start >= $total) return '';
if ($length === null) {
$end = $total;
} elseif ($length < 0) {
$end = $total + $length;
} else {
$end = $start + $length;
}
$end = min($end, $total);
$result = implode('', array_slice($chars, $start, $end - $start));
if ($end < $total) $result .= $suffix;
return $result;
}
// 使用範例
$str = "你好世界,Hello World";
echo utf8_substr($str, 0, 4); // "你好世..."
echo utf8_substr($str, 4); // "界,Hello World"
<?php
function substr_cut($str, $length) {
if (strlen($str) <= $length) return $str;
$result = '';
$len = 0;
for ($i = 0; $i < $length; $i++) {
if (isset($str[$i])) {
$result .= $str[$i];
// 簡易判斷:ASCII 碼 > 128 視為中文字元第一個位元組
if (ord($str[$i]) > 128) {
$i++; // 跳過第二個位元組
if (isset($str[$i])) $result .= $str[$i];
}
}
}
return $result . '..';
}
缺點:僅適用 GBK/Big5 或簡易 UTF-8,不建議生產環境使用。
| 方法 | 支援編碼 | 效能 | 建議場景 |
|---|---|---|---|
mb_substr() | UTF-8, GBK, Big5 等 | 高 | 生產環境首選,需 mbstring 擴充 |
preg_match_all /u | UTF-8 完整支援 | 中 | 無 mbstring 環境,需精確處理 Emoji |
| 簡易 ord() 判斷 | 不完整 | 高 | 舊專案維護、特定編碼環境 |
php-mbstring 擴充套件mb_substr() 為專案通用函數 str_cut()utf8mb4 支援完整 Unicode