我們都知道Yii可以跨Controller使用function (ex: UserController::ShowHallo), 但是很多時候我們會希望一個過濾器(filter)能讓許多的Controller共用.
因為我們不用再重複寫一樣的cord, 是吧! 正如《Clean Code》的Bob大叔說的:不要重複自己DRY (Don't Repeat Yourself)
步驟:
1. 在protected/下建立一個資料夾 (ex: filers)
2. 在protected/filers下建立一個檔案 (ex: ShowHalloFilter.php)
3. 幫你的filter寫點東西
4. 在要使用的Controller裡的filers用array ('application.filters.ShowHalloFilter + aboutMe, fuckYou')的方式來使用我們建立的filter
來實作吧! 包含錯誤示範(假設步驟1.2已完成, 以下是從步驟3開始)
ShowHalloFilter.php (位置:protected/filers/)
class ShowHalloFilter extends CFilter
{
protected function preFilter($filterChain) //preFilter會在你的action前執行
{
echo 'Hallo, I'm Joker.';
$filterChain->run(); <- 錯誤, 把他刪掉就對了
return true;
}
protected function postFilter($filterChain) //postFilter會在你的action後執行
{
echo 'ㄟ....我不是已經介紹過我了嗎?';
}
}
出現問題:
沒有顯示錯誤訊息, 但是你會發現你套用的action會被執行兩次! 為什麼呢?
參考官方說明:看他下面的 filter()方法
看來是因為我們繼承的CFilter時, 他的function filter本身就會在執行完preFilter後, 執行我們的action, 所以如果我們像上面一樣加上$filterChain->run(); 的話就會再執行一次.
PS: 以上只是個人的猜測, 因為為什麼他會執行CFilter的filter這個function? 我實在找不到原因, 如果知道的大大還煩請賜教, 謝謝.
UserController.php (位置:protected/controllers)
class UserController extends Controller
{
public function filters()
{
return array(
'accessControl', // perform access control for CRUD operations
'postOnly + delete', // we only allow deletion via POST request
'application.filters.ShowHalloFilter + aboutMe, fuckYou', <- 錯誤
array ('application.filters.ShowHalloFilter + aboutMe, fuckYou'), <- 正確
);
}
}
出現錯誤:
Filter "application.filters.CheckFbLoggedFilter" is invalid. Controller "UserController" does not have the filter method "filterapplication.filters.ShowHalloFilter".
簡單的說就是這樣寫會讓Yii以為在UserController裡有個filter叫filterapplication.filters.CheckShowHalloFilter, 所以會發生錯誤.
小問題: (希望有大大能解惑)
我中間有嘗試在ShowHalloFilter.php裡建立第二個Class, 想說不知道可不可以一個檔案放多個filter, 結果失敗了! 不知道是Yii本身的規定 (怕會太過混亂?), 還是其實有其他方式可行?
沒有留言:
張貼留言