[后端]定制CodeIgniter-自定義控制器與錯誤處理

前言

使用現(xiàn)有的codeigniter還不能很好地滿足我們業(yè)務(wù)的需求拢操,比如在做一個API服務(wù)器的時候僚焦,一些權(quán)限驗證宇弛,格式輸出的事情都比較難完成,如果都單獨寫在各個controller里的話就顯得冗余不可維護腰耙。所以我們要對Codeigniter進行一些特殊的定制榛丢。

自定義控制器

原本的CI_controller是所有controller的父類,其功能是簡單的挺庞。我們還希望對于controller以及每個調(diào)用的函數(shù)都做一些統(tǒng)一的工作晰赞,比如權(quán)限驗證、輸入驗證选侨、輸出格式等等掖鱼。所以我們有必要自己再封裝一層controller的基類。具體描述如下:

  • override _remap($method, $params)
    這個函數(shù)在每個controller成員函數(shù)被調(diào)用前都會被調(diào)用援制,參數(shù)$method表示當前被調(diào)用的函數(shù)戏挡,$params表示傳遞的參數(shù)。我們可以對這個在這個函數(shù)里面做一些目標函數(shù)被調(diào)用時候的預(yù)處理晨仑,接著調(diào)用call_user_func_array來執(zhí)行真正的函數(shù)增拥,并得到結(jié)果。

  • override __destruct()
    這個解構(gòu)函數(shù)中寻歧,我們可以做一些做一些輸出格式化的工作掌栅。CI中的$this->output類是框架帶有的輸出類,我們controller控制過程中的load->view其實都是被這個類給緩存下來了码泛,只有當調(diào)用$this->output->_display()后才會真正傳輸?shù)綖g覽器中(默認的猾封,_display()會自動在output析構(gòu)的時候調(diào)用)。我們可以在__destruct中對輸出進行一些定制噪珊,比如對call_user_func_array的輸出封裝一些格式化的東西晌缘。

  • 步驟

  • step1 在application/config/config.php中,配置修改$config['subclass_prefix']一行代碼痢站,開啟對API_自定義類的自動加載磷箕。

$config['subclass_prefix'] = 'API_';
  • step2 新建application/core/API_Controller并編輯成如下內(nèi)容。函數(shù)內(nèi)部的內(nèi)容是自定義的阵难,這里只是舉個返回json的例子岳枷。
class API_Controller extends CI_Controller {
     function __construct()
     {
         parent::__construct();
         $this->result = array();
     }

     function _remap($method, $params = array()){
         $methodResult = call_user_func_array(array($this, $method), array());
         $this->result['result'] = $methodResult;
         return $methodResult;
     }

     function __destruct(){
         $this->result['msg'] = 'success';
         $this->output->set_content_type('json'); 
         $this->output->set_output(json_encode($this->result));
         $this->output->_display();
     }
}
  • step3 修改自己的業(yè)務(wù)controller繼承這個API_Controller即可。

自定義錯誤處理

服務(wù)端經(jīng)常發(fā)生程序在業(yè)務(wù)上遇到邏輯錯誤的情況,比如余額不足無法購買空繁,沒有登錄這樣的錯誤處理信息殿衰。處理錯誤返回在原來也是一個比較麻煩的事情,要寫一大堆判斷和返回錯誤碼來告訴客戶端相對應(yīng)錯誤盛泡。為了解決這個錯誤處理的問題闷祥,我們用異常來解決這件事情。我們向框架統(tǒng)一注冊一個底層的異常處理程序傲诵,這樣在業(yè)務(wù)處理錯誤的時候凯砍,任何地方都可以threw一個異常。底層異常處理程序捕獲異常之后拴竹,根據(jù)異常取出相關(guān)的信息果覆,統(tǒng)一處理或者封裝之后返回給客戶端,就解決了這個令人頭疼的錯誤處理殖熟。

  • _exception_handler
    原來框架有定義了錯誤處理局待,在system\core\CodeIgniter.php中有如下的描述。
   set_error_handler('_error_handler');
   set_exception_handler('_exception_handler');
   register_shutdown_function('_shutdown_handler');

分別表示發(fā)送運行錯誤的時候用_error_handler函數(shù)來處理菱属,發(fā)生未捕獲的異常的時候用_exception_handler來處理钳榨,showdown的時候用_shutdown_handler處理。這三個函數(shù)都在system\core\Common.php被定義纽门。

理論上我們修改Common.php中這三個函數(shù)的內(nèi)容就行了薛耻。但是原則上我們不應(yīng)該去修改system目錄下的文件。所以我們換一種方式赏陵,只要搶先聲明_exception_handler就可以override這個異常處理了饼齿,其他幾個函數(shù)要定制的話也是同理。

我們發(fā)現(xiàn)applicaiton下有個constants.php的文件是在Common.php的文件前被引入的蝙搔,所以自然地我們在constants.php中做一些手腳缕溉。

  • 步驟
    step1 新建文件application\core\exception\exception_handler.php,編輯如下
 <?php
if(!function_exists('_exception_handler')){
   function _exception_handler($exception){
       $_error =& load_class('Exceptions', 'core');
       $_error->log_exception('error', 'Exception: '.$exception->getMessage(), $exception->getFile(), $exception->getLine());

       // Should we display the error?
       if(true){
           $statusCode = method_exists($exception, 'getStatusCode')?$exception->getStatusCode():500;
           set_status_header($statusCode);
           !class_exists('CI_Controller') OR $ci = get_instance();
           $ci->result['err'] = $statusCode;
       }

       exit(1); // EXIT_ERROR
   }
}

step2 在application\config\constants.php文件末尾添加上

 require_once (APPPATH.'core/exception/exception_handler.php');

這樣就完成了復(fù)寫_exception_handler的工作吃型。一些基礎(chǔ)的自定義Exception類也可以放在application\core\exception\目錄下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末证鸥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子勤晚,更是在濱河造成了極大的恐慌枉层,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赐写,死亡現(xiàn)場離奇詭異鸟蜡,居然都是意外死亡,警方通過查閱死者的電腦和手機挺邀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門揉忘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跳座,“玉大人,你說我怎么就攤上這事癌淮√煞兀” “怎么了沦补?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵乳蓄,是天一觀的道長。 經(jīng)常有香客問我夕膀,道長虚倒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任产舞,我火速辦了婚禮魂奥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘易猫。我一直安慰自己耻煤,他們只是感情好,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布准颓。 她就那樣靜靜地躺著哈蝇,像睡著了一般。 火紅的嫁衣襯著肌膚如雪攘已。 梳的紋絲不亂的頭發(fā)上炮赦,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機與錄音样勃,去河邊找鬼吠勘。 笑死,一個胖子當著我的面吹牛峡眶,可吹牛的內(nèi)容都是我干的剧防。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼辫樱,長吁一口氣:“原來是場噩夢啊……” “哼诵姜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起搏熄,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤棚唆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后心例,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宵凌,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年止后,在試婚紗的時候發(fā)現(xiàn)自己被綠了瞎惫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溜腐。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瓜喇,靈堂內(nèi)的尸體忽然破棺而出挺益,到底是詐尸還是另有隱情,我是刑警寧澤乘寒,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布望众,位于F島的核電站,受9級特大地震影響伞辛,放射性物質(zhì)發(fā)生泄漏烂翰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一蚤氏、第九天 我趴在偏房一處隱蔽的房頂上張望甘耿。 院中可真熱鬧,春花似錦竿滨、人聲如沸佳恬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽毁葱。三九已至,卻和暖如春曙砂,著一層夾襖步出監(jiān)牢的瞬間头谜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工鸠澈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留柱告,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓笑陈,卻偏偏與公主長得像际度,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子涵妥,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

推薦閱讀更多精彩內(nèi)容