由 Smarty 移轉至 CodeIgniter

前言

在網路上,使用 CodeIgniterSmarty 當關鍵字,可以找到的資料大部分都是如何結合兩者一起使用,唯獨此篇文章,是要完全移除 Smarty ,純粹使用 CI。會這樣做,是因為接手別人先前用 Smarty 開發的程式,但自己不想同時使用多種開發環境,故將 Smarty 的 template 以 CI 的 View 取代。

在這裡介紹的方式,比較像是 refractor,一點一點,無痛的慢慢的移。以我目前進行中的程式為例,到現在只進行到將一般使用者的這部分完全改成 CI,管理端則尚未動。而目前所做的也不過是在 Controller 中將原來的程式 include 進來,然後在運作中根據反應修正錯誤。等穩定後,再來拆成對應的 model 和 controller。我自己是蠻享受這種漸進過程,今天改一些這裡,過幾天又改一些那裡,慢慢看著成果一點一點呈現。

步驟

因為在 template 中,圖示和 CSS 都是用相對目錄,所以啟用 query string 來指定 controllers 和 functions,等以後再來修正相對路徑的問題。

修改 config.php 的設定

// 把 Smarty 改成 view, 先停用 Smarty
// 避免過多的錯誤, 先用 query string 指定 controllers 和 functions
$config['enable_query_strings'] = TRUE;  // FALSE;
$config['controller_trigger']   = 'c';
$config['function_trigger']     = 'm';
$config['directory_trigger']    = 'd'; // experimental not currently in use

修改之後, 用 c 及 m 來指定 controller 及 function

http://myweb.net.tw/myapp/index.php?c=User&m=index

假如是在子目錄下, 例如 application/controllers/tt/ 下

則為

http://myweb.net.tw/myapp/index.php?d=tt&c=User&m=index

這樣修改之後,在 html 中原來使用相對目錄指定 image, css, js 就可以用了。

1. 先在controller 的 method 中 include 原來的 php,變成 controller 的一個 method。

View仍維持使用 Smarty,確定所有的獨立的 php 程式都變成 controller 的 method。

vod_series_edit.php?operator=del

改為

   ?c=Admin&m=vod_series_edit&operator=del

2. 接下來將 Smarty 的 template 改成 CI 的 View。

將所有的 template 複製到 view 的目錄下,將副檔名由 *.tpl 改為 *.php。

3. 當把 .tpl 檔都完全正確地改成 .php 之後,即可依 MVC 的方式重新調整程式。

將原來的 php 程式變成 CI 的 controller 中的 method

在 Controller 的 function 直接 inclucde 原來的 php 程式,例如:

public function index(){
   global $ci_data;
   include('../user/index.php');
}

因為原來的程式變成 function 了, 所以有一些公用變數要宣告 global 變數,例如

// 變成 CI 的 function 了, 會看不到 global variables
global $db, $smarty, $app_path;
global $key_no_cnt_ary;
global $ci_data;

其中,$ci_data 是在後面要

依上述方式將獨立的php程式變成controller的method之後,執行看看是否正確,若有問題,試著修改到完全正確。然後,就可以進行下一步驟,把smarty完全移除。

將 Smarty 的 template 改成 CI 的 View

將 Smarty 的 display() 改成 CI 的 load->view()。因為是在 include 的 php 程式中呼叫,要先用get_instance() 取得 CI 的 reference。例如

  $smarty->display("vod_film.tpl");

置換成

$CI =& get_instance();
$CI->load->view('vod_film', $ci_data);

傳遞參數方式的修改如下。

$smarty->assign('film', $film);

置換成

$ci_data['film'] = $film;

在 template 中載入另一個 template 的修改如下。

{include file="vod_play.tpl"}

置換成

<?php $this->load->view("vod_play"); ?>

在 template 中,修改參數的顯示。簡單的將 {$xx} 換成 <?=$xx;?> 即可。

這樣的置換,的確是字數變多了,但還好。

{section} ... {/section} 改成 for loop,至於 {if} ... {/if} 的修改就更直接了。

最後,在 form 的修改會比較囉唆些,但應該也是不難的。

結語

完全將 Smarty 移除之後,剩下的就只要完全照 CI 的 MVC 架構慢慢整理程式即可。例如,先將資料庫的程式碼搬到 model,再將剩下的部分塞到 controller 的 function 中就完成了。如此,我就可以全心在 CI 上開發了。

參考

收集了一些相關的說法,讓自己更加肯定不需要使用樣版!

連結: http://codeigniter.com/nightly_user_guide/overview/at_a_glance.html

CodeIgniter Does Not Require a Template Engine

Although CodeIgniter does come with a simple template parser that can be optionally used, it does not force you to use one. Template engines simply can not match the performance of native PHP, and the syntax that must be learned to use a template engine is usually only marginally easier than learning the basics of PHP. Consider this block of PHP code:

<ul> <?php foreach ($addressbook as $name):?> <li><?=$name?></li> <?php endforeach; ?> </ul>

Contrast this with the pseudo-code used by a template engine:

<ul> {foreach from=$addressbook item="name"} <li>{$name}</li> {/foreach} </ul>

Yes, the template engine example is a bit cleaner, but it comes at the price of performance, as the pseudo-code must be converted back into PHP to run. Since one of our goals is maximum performance, we opted to not require the use of a template engine.

另外在 Proposal for MVC Interfaces 有這麼一句話:

"Currently, ZF only offers a single view strategy, based on using PHP as a template language."

在 PHP 5.4 中,雖然預設 short open tag "<?" 是關掉的,但是 "<?=" 則是永遠可以用的,這目的應該也是為了不用弄個 template engine 來增加複雜度。