2009年8月20日 星期四

Smarty隨手筆記

這兩天閒來無事稍微研究了一下Smarty
Smarty
是PHP用的一套樣版引擎
這東西就像是.NET的MasterPage,可以把頁面Template(樣版化)動態輸出
這樣一來就可以標準化網頁,不過個人不喜歡MasterPage的作法就是了

之前旗標也有出Smarty的書籍,不過網路上已經也有很多相關教學了
Smarty並不是很龐大,說明手冊花個兩三個小時大概就能讀完了
加上有前人很熱情的放出中文化中說明手冊,要自學也不用花什麼工夫
附上幾個我參考到的網站


當初覺得Smarty應該要花不少時間去學,真的開始看說明手冊以後其實不然
不考慮研究核心code的話,其實很快就能把整個功能面跟觀念說完了
上面幾篇文章都說的非常清楚了,下面只是我一些研究過程的隨筆

Extended Setup這篇有附上一段程式碼,這段code很重要

class Smarty_GuestBook extends Smarty {

function Smarty_GuestBook()
{
$this->Smarty();
$this->template_dir = '/web/www.example.com/guestbook/templates/';
$this->compile_dir = '/web/www.example.com/guestbook/templates_c/';
$this->config_dir = '/web/www.example.com/guestbook/configs/';
$this->cache_dir = '/web/www.example.com/guestbook/cache/';
$this->caching = true;
$this->assign('app_name', 'Guest Book');
}

}

他建議我們擴充Smarty類別,把一些設定都先設定好
一開始要指定幾個資料夾,template_dircompile_dirconfig_dircache_dir
這四個最常用的,其他還有一些延伸資料夾可以指定,但是在此先不探討
  1. template_dir:樣版網頁放置地方,使用display() 函式的時候會去template_dir指定的地方尋找樣版
    預設是./templates
  2. compile_dir:Smarty會把樣版網頁先編譯成對應格式,這是編譯結果放的網頁,預設是./templates_c
  3. config_dir:Smarty允許事先弄一些設定檔出來,預設是放./configs
    使用
    config_load() 載入config的時候他會去config_dir指定的資料夾找檔案
    他官網提供的config編寫範例

    # global variables
    pageTitle = "Main Menu"
    bodyBgColor = #000000
    tableBgColor = #000000
    rowBgColor = #00ff00

    [Customer]
    pageTitle = "Customer Info"

    [Login]
    pageTitle = "Login"
    focus = "username"
    Intro = """This is a value that spans more
    than one line. you must enclose
    it in triple quotes."""

    # hidden section
    [.Database]
    host=my.example.com
    db=ADDRESSBOOK
    user=php-user
    pass=foobar
  4. cache_dir:如果有設定快取(caching是true),他會產生一份compile_dir裡面編譯檔的最後輸出
    預設資料夾是 ./cache




而我照自己的需求去擴展一個Smarty,並創造一個smartyDir資料夾,下面放Smarty須要用到的資料夾
我把類別庫放在Smarty/libs下面,只要include其中的Smarty.class.php就可以了

include_once ('Smarty/libs/Smarty.class.php');
define("APPDIR","smartyDir/");
class MySmarty extends Smarty{
function MySmarty(){
$this->template_dir=APPDIR."templates";
$this->compile_dir=APPDIR."templates_c";
$this->config_dir=APPDIR."config_dir";
$this->cache_dir=APPDIR."cache";
}
/*更改阻斷符號 預設是{跟}*/
function setDelimiter($Lcode,$Rcode)
{
$this->left_delimiter=$Lcode;
$this->right_delimiter="$Rcode";
}
}
?>



我先在templates資料夾裡面建一個樣版檔案mytemp.tp

mytemp.tp內容

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
{$page}
</body>
</html>


其中{$page}是Smarty可用的變數,將來可以用來替換自己想要的內容
變數的使用方法可以參考Variables這篇說明文件
簡介幾種常用的方式

  • {$foo} <-- displaying a simple variable (non array/object)
    指派一般變數,使用assign指派內容
    $tp1=new MySmarty();
    $tp1->assign("foo","Hello");

  • {$foo[4]} <-- display the 5th element of a zero-indexed array
    指派一個陣列
    $arr=array(1,2,3,4,5);
    $tp1->assign("foo",$arr);

  • {$foo.bar} <-- display the "bar" key value of an array, similar to PHP $foo['bar']
    指派關聯陣列
    $arr=array('bar'=>'I am God');
    $tp1->assign("foo",$arr);

  • {$foo->bar} <-- display the object property "bar"
  • {$foo->barf()} <-- display the return value of object method "bar"
    指派一個物件
    class Foo{
    var $bar;
    function barf(){......}
    }
    $obj=new Foo();
    $tp1->assign("foo",$obj);
  • {#foo#}       <-- display the config file variable "foo"
    使用config_load() 載入的設定內容
    ex:有個conf.txt內容是
    foo=MyGod



之後php程式碼的部分就可以用assign指派我們想要的內容

$tp2=new MySmarty();
$tp2->assign("page","Hello Smarty");/*指派Smarty變數內容*/
$tp2->caching=true;/*開啟快取*/
$tp2->display("mytemp.tp");/*顯示網頁*/

執行結果


題外話,一開始我一直以為display() 函式是去程式同一個資料夾找樣版
所以一開始我沒把樣版放在templates資料夾裡面
所以一直會出現錯誤訊息

Smarty error: unable to read resource........


那剛剛秀出網頁做了些什麼呢?

首先我display()去顯示templates資料夾下的mytemp.tp


之後會在我指定的編譯資料夾templates_c下產生一個編譯過的檔案%%9B^9B3^9B3C2773%%mytemp.tp.php,此時他還是一個php的動態檔


來看一下他編譯了什麼東西出來


<?php /* Smarty version 2.6.26, created on 2009-08-21 02:07:52
compiled from mytemp.tp */ ?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<?php echo $this->_tpl_vars['page']; ?>

</body>
</html>


原來的樣版檔案,變成一個我們都很熟悉的PHP檔,Smarty變數的部分被PHP碼所取代
但是這樣很慢,要把樣版(Template)解譯成PHP檔,又要把PHP檔編譯成網頁

所以Smarty提供了cache的機制
當我設定cache的時候,,他會在我指定的cache資料夾產生一個已經編譯好的靜態網頁
這樣下次要access的時候直接用這個就可以了,不用重新編譯


來看看cache的內容

130
a:4:{s:8:"template";a:1:{s:9:"mytemp.tp";b:1;}s:9:"timestamp";i:1250821113;s:7:"expires";i:1250824713;s:13:"cache_serials";a:0:{}}<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
Hello Smarty
</body>
</html>


除了原本編譯好的網頁之外,還有一串header包括了timestamp
cache並不會永遠存在,過了一段時間後就會被刪除,預設是一個小時
可以透過cache_lifetime修改生存時間

不過如果同個樣版有多種內容的話(ex:資料庫的資料),就必須設定cache_id作辨別
一般會用user下的query作hash來產生cache_id

另外我在寫程式的時候,發現他會跟css碼或者javascript相衝,因為他的阻斷符號是{跟}
正好跟css設定方法有衝突,可以透過left_delimiterright_delimiter重新設定阻斷符號
像我是設定成,這樣就不會跟css碼相衝了

$tp1->setDelimiter("<!--{","}--<");/*這是我自定的函式,請參考上方的MySmarty*/

之後我在標記Smarty變數就會從

......
{$page}
......

變成用下面這種方式

<!--{$page}-->

因為是用HTML註解的方式去從新包裝,這樣一來也比較不會有問題

其他更多的內容,包括註冊自己的函式跟區塊、if else 、loop迴圈等等,就請去翻說明手冊啦
手冊有更多詳盡的內容

備註:上面的連結Smarty中文說明手冊
都可以找到相對應的翻譯

沒有留言: