ThinkPHP 內建 msubstr() 函數在字串被截斷時,未自動附加省略號(...),導致前端顯示不完整。
編輯 Common/extend.php 覆蓋原函數:
<?php
function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true) {
// mbstring 擴展優先
if (function_exists("mb_substr")) {
$slice = mb_substr($str, $start, $length, $charset);
if ($suffix && $slice !== $str) {
return $slice . "...";
}
return $slice;
}
// iconv 回退
if (function_exists('iconv_substr')) {
$slice = iconv_substr($str, $start, $length, $charset);
if ($suffix && $slice !== $str) {
return $slice . "...";
}
return $slice;
}
// 純 PHP 正則備援(UTF-8/GB2312/GBK/BIG5)
$re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
$re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
$re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
preg_match_all($re[$charset], $str, $match);
$slice = join("", array_slice($match[0], $start, $length));
if ($suffix && $slice !== $str) {
return $slice . "…"; // 使用 Unicode 省略號
}
return $slice;
}
| 原版問題 | 修正邏輯 |
|---|---|
| 無條件加上省略號 | 比較 $slice !== $str,僅在真正截斷時添加 |
| mb_substr/iconv_substr 回傳值未判斷 | 統一變數 $slice 判斷 |
| 正則備援編碼支援不全 | 保留原編碼正則,補上 Unicode 省略號 |
<?php
$text = "這是一段很長的測試文字,用來驗證 msubstr 函數是否正確添加省略號。";
echo msubstr($text, 0, 10); // 輸出:這是一段很長的測...
echo msubstr($text, 0, 100); // 輸出:完整文字(無省略號)
echo msubstr($text, 0, 10, 'utf-8', false); // 輸出:這是一段很長的測(無省略號)
mbstring 或 iconv 擴展,正則備援效能極差LEFT()/SUBSTRING() 或前端 CSS text-overflow: ellipsis 處理str_limit() / mb_strimwidth() 更推薦使用