讓 Smarty 的 truncate 支援 utf-8






我用 PHP 搭配 Smarty template engine
習慣搭配 truncatedate_format 等 smarty 內建函數
方便日後設計人員可更改
這樣也可讓邏輯端的程式精簡些

有好一陣子沒用 Smarty 了
最近在翻閱之前的作品參考
突然看到用 utf-8 編碼格式的怎麼突然會有亂碼
先將 Smarty 版本更新到目前最新的 2.6.18
然後清掉 compile 的 cache 檔
情形還是一樣

在網路上搜尋後發現有不少教學文
大多都是自己加個 plugin
然後將呼叫 truncate 的函式改為 truncate_utf8 之類的

以下為這支 plugin:

// http://dev.splitbrain.org/view/darcs/dokuwiki/inc/utf8.php

/**
* UTF8 helper functions
*
* @license LGPL (http://www.gnu.org/copyleft/lesser.html)
* @author Andreas Gohr
*/


if(!defined('UTF8_MBSTRING')){
if(
function_exists('mb_substr') && !defined('UTF8_NOMBSTRING'
)){
define('UTF8_MBSTRING',1
);
}else{
define('UTF8_MBSTRING',0
);
}
}

if(
UTF8_MBSTRING){ mb_internal_encoding('UTF-8'
); }

function utf8_strlen($string){
return
strlen(utf8_decode($string
));
}

function utf8_substr($str, $offset, $length = null) {
if(
UTF8_MBSTRING
){
if(
$length === null
){
return
mb_substr($str, $offset
);
}else{
return
mb_substr($str, $offset, $length
);
}
}

$str = (string)$str;

$offset = (int)$offset
;
if (!
is_null($length)) $length = (int)$length
;

if ($length === 0) return ''
;
if (
$offset < 0 && $length < 0 && $length < $offset) return ''
;

$offset_pattern = ''
;
$length_pattern = ''
;

if ($offset < 0
) {
$strlen = strlen(utf8_decode($str));
$offset = $strlen + $offset;
if (
$offset < 0) $offset = 0
;
}

if ($offset > 0
) {
$Ox = (int)($offset/65535
);
$Oy = $offset%65535
;

if (
$Ox) $offset_pattern = '(?:.{65535}){'.$Ox.'}'
;
$offset_pattern = '^(?:'.$offset_pattern.'.{'.$Oy.'})'
;
} else {
$offset_pattern = '^';
}

if (is_null($length
)) {
$length_pattern = '(.*)$';

} else {

if (!isset(
$strlen)) $strlen = strlen(utf8_decode($str));

if ($offset > $strlen) return '';


if ($length > 0
) {

$length = min($strlen-$offset, $length);


$Lx = (int)($length/65535
);
$Ly = $length%65535
;

if ($Lx) $length_pattern = '(?:.{65535}){'.$Lx.'}'
;
$length_pattern = '('.$length_pattern.'.{'.$Ly.'})'
;

} else if (
$length < 0
) {

if (
$length < ($offset - $strlen)) return ''
;

$Lx = (int)((-$length)/65535
);
$Ly = (-$length)%65535
;

if ($Lx) $length_pattern = '(?:.{65535}){'.$Lx.'}'
;
$length_pattern = '(.*)(?:'.$length_pattern.'.{'.$Ly.'})$'
;
}
}

if (!
preg_match('#'.$offset_pattern.$length_pattern.'#us',$str,$match)) return ''
;
return
$match[1
];
}

function smarty_modifier_truncate_utf8($string, $length = 80, $etc = '...', $break_words = false, $middle = false)
{
if (
$length == 0
)
{
return
''
;
}

if(
utf8_strlen($string) > $length
)
{
$length -= utf8_strlen($etc
);

if(!
$break_words && ! $middle
)
{
$string = preg_replace('/\s+?(\S+)?$/us', '', utf8_substr($string, 0, $length+1
));
}

if(!
$middle
)
{
return
utf8_substr($string, 0, $length) . $etc
;
}
else
{
return
utf8_substr($string, 0, $length / 2) . $etc . utf8_substr($string, -$length / 2
);
}
}
else
{
return
$string
;
}
}
?>

使用方法很簡單
將上面的 code 另存新檔為 modifier.truncate_utf8.php
放至 Smarty-x.x.x/libs/plugins 下

由於 plugins 下已經存在 Smarty 內建的 plugins
如果你怕下次更新 Smarty 會忽略到的話
可自訂一個 plugins 的資料夾如 Smarty-x.x.x/libs/my_plugins
可在程式中加入
$smarty->plugins_dir[] = 'Smarty-x.x.x/libs/my_plugins';
即可


參考來源:
让“Smarty truncate modifier plugin”支持UTF-8

Comments

Popular posts from this blog

CentOS7 如何新增/移除 Rich Rule for firewalld

mac 安裝 mtr

如何設定 SSL VPN 分割通道 on Fortigate 80C