function cutstr($string, $length, $dot = '...')
$length 為字元寬度(中文算 2,英文數字算 1),超出則截斷並附加 $dot。
$length 直接返回。&、"、<、> 替換為控制字元 chr(1) 包裹,防止截斷導致實體殘缺。| 首位元組 | 位元組數 | 顯示寬度 |
|---|---|---|
| 0x09,0x0A,0x20-0x7E | 1 | 1 |
| 0xC2-0xDF | 2 | 2 |
| 0xE0-0xEF | 3 | 2 |
| 0xF0-0xF7 | 4 | 2 |
| 0xF8-0xFB | 5 | 2 |
| 0xFC-0xFD | 6 | 2 |
採用簡單雙位元組判斷(ord > 127 視為雙位元組字元),逐字元疊加至長度。
$str = "你好世界 Hello World";
echo cutstr($str, 10); // 你好世界...
echo cutstr($str, 10, '[...]'); // 你好世界[...]
// 使用 mbstring(需擴展)
function cutstr_mb($string, $length, $dot = '...') {
if (mb_strwidth($string) <= $length) return $string;
return mb_strimwidth($string, 0, $length, $dot, 'UTF-8');
}
// 使用 grapheme(PHP 7.0+,支援 Emoji 等字素叢集)
function cutstr_grapheme($string, $length, $dot = '...') {
$clusters = grapheme_str_split($string);
$width = 0; $result = '';
foreach ($clusters as $g) {
$w = (preg_match('/^[\x00-\x7F]$/', $g) ? 1 : 2);
if ($width + $w > $length) break;
$result .= $g; $width += $w;
}
return $result . ($width < mb_strwidth($string) ? $dot : '');
}
建議:生產環境優先使用 mb_strimwidth 或 grapheme_*,相容性更佳、效能更高、支援完整 Unicode。