前言
使用現(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\目錄下