因為升級成 Codeignitor4(以下全稱為ci4) 加上習慣使用 smarty,因此在 view表上決定使用 smarty5(以下皆稱smarty)。
先決條件,你已經安裝完畢 ci4,我是使用git來安裝(可以參考這裡),當然你也可以使用composer來安裝,因為smarty5預計使用composer來安裝。
ci4 要整合和 smarty5 一起用,需要異動的檔案有一些多,你可以視需要調整。如果你只想用smarty4 的話,可以參考ci4+smarty4這篇。
系統
Rocky Linux release 9.0 (Blue Onyx)
Docker 20.10.21
└─ PHP 8.2.17
└─ Codeignitor 4.5.0
安裝smarty5
第5版的smarty安裝,官網似乎停運了?採用 github 來安裝 [2]。
(github上[1]說明用composer來裝,但在docker中這樣要重建container,我覺得很麻煩,所以採用git來安裝)
進到 ci4 的目錄 app/ThirdParty 中
$ cd path/to/app/ThirdParty
$ git clone https://github.com/smarty-php/smarty.git
在ThirdParty目錄下看到以下的檔案:
└── smarty
├── changelog
├── CHANGELOG.md
├── composer.json
├── CONTRIBUTING.md
├── demo
├── docker-compose.yml
├── docs
├── LICENSE
├── Makefile
├── make-release.sh
├── mkdocs.yml
├── phpunit.xml
├── README.md
├── run-tests-for-all-php-versions.sh
├── run-tests.sh
├── SECURITY.md
├── src <== 邏輯上只需要保留這個,其它可以刪掉
├── tests
├── TODO.txt
└── utilities
上面的目錄只有src/的目錄有用,所以搬移 src/ 目錄並改名
$ mv smarty/src/ ./smarty5/
$ rm -rf smarty
到 app/Config 建立 Smarty5 的目錄
$ cd /path/to/app/Config/
$ mkdir Smarty5
建立這目錄是考慮過後最適合放 smarty的config檔的位置,這個目錄並非必要,如果你沒有smarty 的config的話。
完工後在ThirdParty目錄下看到以下的目錄:
└── smarty5
設定SMARTY服務
這次要異動的檔案如下:
app
├── Config
│ ├── Smarty5 <== smarty的config檔放置位置
│ ├── Services.php <== 註記服務
│ └── Autoload.php <== 註記Smarty的命名空間
├── Libraries
│ └── Smarty5.php <== 建立Smarty5 物件
├── ThirdParty
│ └── smarty5 <== 上面已將 smarty5 裝在這裡
│ └── Smarty.php <== 讀取此檔即可
└── Views
└── <樣版放這裡>
並在在writable/目錄下建立兩個可寫入的目錄
└── writable
├── cache
└── templates_c
修改Config
註記Smarty的命名空間 App/Config/Autoload.php
修改 $psr4
public $psr4 = [ APP_NAMESPACE => APPPATH, 'Smarty' => APPPATH . 'ThirdParty/smarty5/', ];
新增第4行。
註記服務 App/Config/Services.php
<?php namespace Config; use CodeIgniter\Config\BaseService; use \App\Libraries\Smarty5; class Services extends BaseService { public static function Smarty5($getShared = true){ if($getShared) { return static::getSharedInstance('Smarty5'); } return new Smarty5; } ... }
新增 5,9-14行。
建立 Smarty5 服務
如果不想要每次設定參數來使用smarty的話,建立一個 library 類別是必要的,新增以下檔案:
App/Libraries/Smarty5.php
<?php namespace App\Libraries; use Smarty; class Smarty5 extends Smarty\Smarty { public function __construct() { parent::__construct(); parent::setTemplateDir(APPPATH . 'Views/'); parent::setConfigDir(APPPATH . 'Config/Smarty5/'); parent::setCompileDir(WRITEPATH . 'templates_c/')->setCacheDir(WRITEPATH . 'cache/'); parent::setLeftDelimiter('{{'); parent::setRightDelimiter('}}'); } public function view($tpl_name) { parent::display($tpl_name); } }
設定寫入暫存檔目錄及cache,同時設定smart標記左右符號。view函式是display的別名。
Controller 中叫用
service('Smarty5')->assign('ip','123.46.79.66')->assign('isipv6', true); service('Smarty5')->view('test_template.tpl');
test_template.tpl 是樣版檔,會到 App/Views/ 中尋找。
Smarty5 預設採用靜態方式載入,共用一個變數。
如果想用動態載入的話,可寫成:
$s = service('Smarty5',false); $s->assign('ip', '1.2.3.4')->assign('isipv6', true); $s->view('test_template.tpl');
解決無法叫用特殊變數 $smarty 的問題
如果在樣版中使用特殊變數 $smarty [4],例如 $smarty.now、$smarty.session、$smarty.cookie 等時出現錯誤:
'Call to undefined function Smarty\Compile\smarty_strtolower_ascii()', in file '/Smarty/Compile/SpecialVariableCompiler.php', at line 44
如同這位[5]老哥問的問題,看來明明函數是放在 functions.php 中但是沒有任何的引用指令。
於是我加了一行手動解決,可能不是很好的方法。
修改 Smarty5 目錄下的 Compile/Base.php 檔:
use Smarty\Compiler\Template;
use Smarty\CompilerException;
require_once dirname(__DIR__). "/functions.php"; // <== 加上這一行
這樣就解決了。
結論是透過網友的幫忙,smarty5+ci4 整合的不錯,也不難,祝大家使用愉快。
參考資料
[1] smarty5 的說明文件 https://smarty-php.github.io/smarty/stable/designers/language-basic-syntax/
[2] ci4官網說明 https://codeigniter.tw/user_guide/index.html
[3] smarty5 文件 https://smarty-php.github.io/smarty/5.x/