Wednesday, December 26, 2007

讓 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

Thursday, December 20, 2007

PHP:Hash function

這年頭 md5 已經不可靠了
幾天前開始用 mhash 來處理 sha256 格式的密碼
由於使用 FreeBSD / PHP 5.1.6 平台的關係
所以就很直覺得使用 mhash() 來替代原本的 md5()
而剛剛在 Windows XP 上執行一樣的程式
發現執行 mhash() 有些問題
查了官網 PHP 發現原來 mhash() 自 PHP 5.3.0 要被打入冷宮了
所以還是乖乖統一用 hash() 來的比較保險!

Note: This extension has been moved to the » PECL repository and is no longer bundled with PHP as of PHP 5.3.0. This extension is obsoleted by Hash.

而 hash() 是從 PHP 5.1.2 才開始支援的
如果有要跨越 PHP 5.1 至 5.3 甚至 PHP 6.0 的程式
在這邊還是先檢查一下 PHP 版本後看要用 mhash() or hash() 好


使用 mhash():
function LoginPassword($PWD)
{
return bin2hex(mhash(MHASH_SHA256, $PWD));
}
注意:使用 mhash 加密時,需再使用 bin2hex() 函式轉換,否則會亂碼!


使用 hash():
function LoginPassword($PWD)
{
return hash('sha256', $PWD);
}

另外使用 hash() 的好處是,他比 mhash() 還支援更多種類的加密方式喔!

mhash 支援的加密方式:
  • MHASH_ADLER32
  • MHASH_CRC32
  • MHASH_CRC32B
  • MHASH_GOST
  • MHASH_HAVAL128
  • MHASH_HAVAL160
  • MHASH_HAVAL192
  • MHASH_HAVAL256
  • MHASH_MD4
  • MHASH_MD5
  • MHASH_RIPEMD160
  • MHASH_SHA1
  • MHASH_SHA256
  • MHASH_TIGER
  • MHASH_TIGER128
  • MHASH_TIGER160

hash 支援的加密方式:
md4 md5 sha1 sha256 sha384 sha512 ripemd128 ripemd160 whirlpool tiger128,3 tiger160,3 tiger192,3 tiger128,4 tiger160,4 tiger192,4 snefru gost adler32 crc32 crc32b haval128,3 haval160,3 haval192,3 haval224,3 haval256,3 haval128,4 haval160,4 haval192,4 haval224,4 haval256,4 haval128,5 haval160,5 haval192,5 haval224,5 haval256,5

Monday, December 17, 2007

用 Google Chart API 幫你畫圖表!

如果你不太會用 GDImageMagick 將表格的數值轉成圖形的話
可以使用 Google Chart API 看看!

利用網址的參數帶入
http://chart.apis.google.com/chart?
chs=200x125
&chd=s:helloWorld
&cht=lc
&chxt=x,y
&chxl=0:|Mar|Apr|May|June|July|1:||50+Kb
參數意義:
  • http://chart.apis.google.com/chart? 為這個 API 的位置
  • & 為區隔各參數的符號
  • chs=200x125 設定這張圖檔的大小
  • chd=s:helloWorld 圖表的數據
  • cht=lc 設定圖表呈現的樣式
  • chxt=x,y 指定 x-軸和 y-軸的座標軸為必填欄位
  • chxl=0:|Mar|Apr|May|June|July|1:||50+Kbx-軸和 y-軸的座標軸

可得到這樣的結果:










目前僅提供五種樣式:

我比較期待 Google API 能夠提供像是 Google Analytics 用 Flash 產生的圖表方式 :p