Smarty 內建 truncate 按字節截取,UTF-8 中文佔 3 字節,直接截斷導致半個字符產生亂碼。
modifier.truncate2.php 放入 Smarty/libs/plugins/ 目錄。{$var|truncate2:100} 即可按字符截取前 100 個字符。templates_c/ 緩存目錄。<?php
function smarty_modifier_truncate2($string, $length = 80, $etc = '...', $count_words = true) {
return substr_utf8($string, 0, $length) . $etc;
}
function substr_utf8($str, $start = 0, $length = -1, $return_ary = false) {
$len = strlen($str);
if ($length == -1) $length = $len;
$r = array();
$n = 0; $m = 0;
for ($i = 0; $i < $len; $i++) {
$x = substr($str, $i, 1);
$a = base_convert(ord($x), 10, 2);
$a = substr('00000000' . $a, -8);
if ($n < $start) {
if (substr($a, 0, 1) == '0') { /* 1-byte */ }
elseif (substr($a, 0, 3) == '110') { $i += 1; }
elseif (substr($a, 0, 4) == '1110') { $i += 2; }
$n++;
} else {
if (substr($a, 0, 1) == '0') { $r[] = substr($str, $i, 1); }
elseif (substr($a, 0, 3) == '110') { $r[] = substr($str, $i, 2); $i += 1; }
elseif (substr($a, 0, 4) == '1110') { $r[] = substr($str, $i, 3); $i += 2; }
else { $r[] = ''; }
if (++$m >= $length) break;
}
}
return $return_ary ? $r : implode("", $r);
}
?>
$start 個字符後,按字符長度提取 $length 個完整字符。mb_substr 依賴 mbstring 擴展的限制,純 PHP 實現。