我的烏拉拉練功坊

請來參觀移植到 Google Firebase 的成績 https://oolala.xyz/ken73chen/

2017年10月1日

PHP 的 smarty 樣板引擎


印象中,常常有人為了用或不用 smarty 這東西在吵架,反對的理由大概是說 PHP 本身就可以混 HTML 進去,再用個 smarty 是多此一舉。


例如,下面這段 PHP: <ul> <?php foreach ($addressbook as $name):?> <li><?=$name?></li> <?php endforeach; ?> </ul> 跟下面這個 smarty 的樣板,其實都是一樣的,所以是多此一舉!

<ul> {foreach from=$addressbook item="name"} <li>{$name}</li> {/foreach} </ul>
其實很不一樣, smarty 樣板的 {foreach ... }{/foreach} 湊成一對,不用教都知道,上面那個 endforeach;,你自己都不用了,還要塞給人家用?還有 foreach 後面那個冒號「:」……結果變成如果畫面跑不出來,還是要給你處裡;smarty 有自己的 debug console,一般來說,作畫面的時候,一定會先開 debug console 看有收到哪些變數,所以不會對 debug console 陌生。

用 smarty 的目的是分工,寫 PHP 的人不用去看 HTML,作畫面的人不用去看 PHP,兩邊都可以獨立作業,改程式的時候不會把畫面改壞,改畫面的時候也不會把程式改壞。

我自己是很愛用 smarty,因為可以這樣子:
$results = $db->query_all('SELECT * FROM `posts` WHERE thisthing=thatthing'); $smarty->assign('results',$results);

smarty 3 改用 OO 的寫法,有箭頭看起來就比較厲害,上面那兩行,PHP 將 DB 撈來的結果一股腦丟給 smarty,接著,作畫面的人開 debug console 就知道收到哪些東西,需要的應該都有,用不到的就…要上線前再去改 SELECT * 。

smarty 的 cache 功能,大概是長這個樣子:

$user_id = filter_input(INPUT_GET,'user_id'); $cache_id = "profile_$user_id"; if(!$smarty->isCached('profile.tpl',$cache_id)) { $user_profile = $db->select("SELECT * FROM `Profiles` WHERE user_id = ?", ....); $smarty->assign('user_profile',$user_profile); } $smarty->display('profile.tpl',$cache_id);

profile.tpl 就是 smarty 的樣板檔案,當樣板檔案首次使用時,smarty 會將他編譯 (compile) 成 PHP 檔,以後就直接用編譯後的 PHP,建議可以將 compile 產生的 PHP 檔案路徑,放在 memory disk,並在正式上線後,將自動 compile 樣板檔案的功能關閉。

config 很好用,例如有一個 system.ini:
base_url = 'https://www.foo.com' image_url = 'https://image.foo.com' 在 smarty 的樣板裡面: {config_load "system.ini"} <img class="logo" src="{#image_url#}logo.png" /> image_url = 'https://image.foo.com' PHP 一樣可以用這個 config 檔案: $config = parse_ini_file(DIR_ROOT.'/configs/system.ini',true);
這樣有一天如果換了 URL,或者把圖檔丟到 CDN 上面去,你只要把這個 system.ini 改一下,然後把 cache 清掉,就收工了。

不過,最困難的其實是……PHP frameworks 都有自己的 views,所以根本沒機會用到 smarty……

這年頭,自己寫 1 行 code,大概會用到 100 行的別人的 code,如果你不打算用包山包海的 frameworks,也有像是 TinyMVC 這種特色是功能不多的 MVC。

或者打算自己來,例如這樣的網址 https://www.foo.com/users/kenchen,其實也可以用 nginx (apache 當然也可以) 的 rewrite,像是這樣 rewrite ^/users/(.*)$ /profile.php?user=$1? last;,沒有實際測試,不過效能應該會比用 controlers 還要高很多。

我不是要反對用 frameworks,frameworks 可以強迫人乖乖的 coding、方便與同事合作,而且看了 frameworks 裡面漂亮的 code,以後自己寫的 code 一定也會漂亮很多。

我個人認為,frameworks 最大的缺點,對  PHP 會越來越陌生……繼續下去會題離太遠,就此打住。

最後提醒,有事沒事就去看一下 PHP: The Right Way


PHP: The Right Way