承接上一篇博文,咱們繼續CI restful改造之旅。php
在第一篇博文裏面簡單介紹了CI的一些加載機制,在此基礎上咱們要對CI進行改造了。與其說是改造不如說是增長一個控制器處理層。html
咱們知道CI的控制器基類在system/core/CodeIginter.php裏面加載,控制器基類主要作了兩個事情git
1.加載各類核心類爲控制器屬性github
2.提供一個控制器實例化方法bootstrap
class CI_Controller { /** * Reference to the CI singleton * @var object */ private static $instance; /** * Class constructor * @return void * 加載各類核心類爲屬性 */ public function __construct() { self::$instance =& $this; // Assign all the class objects that were instantiated by the // bootstrap file (CodeIgniter.php) to local class variables // so that CI can run as one big super object. foreach (is_loaded() as $var => $class) { $this->$var =& load_class($class); } $this->load =& load_class('Loader', 'core'); $this->load->initialize(); log_message('info', 'Controller Class Initialized'); } // -------------------------------------------------------------------- /** * Get the CI singleton * @static * @return object * 提供一個獲取控制器實例化的方法 */ public static function &get_instance() { return self::$instance; } }
一般咱們在application/controller中增長控制器都要繼承這個基類才能正常運行。restful
爲了在不改變CI核心類的基礎上對框架進行改造,咱們選擇擴展這個核心類,並不修改它。app
基於以上目的,我選擇在CI_Controller與應用控制器以前增長一箇中間層,這樣咱們在application/core/下新增一個文件叫rest.php框架
defined('BASEPATH') OR exit('No direct script access allowed'); /** * restful 核心類 * @class rest * extends CI_Controller */ class rest extends CI_Controller{ /** * 構造函數 */ public function __construct() { parent::__construct(); } }
首先,咱們須要繼承CI_Controller以得到CI核心類的訪問權限(注意:parent::__construct();這句必定要加上,由於涉及到CI加載核心類文件)。ide
到目前爲止,咱們已經邁出了改造的第一步,但不論從哪一個角度看咱們添加的這個中間層都不像一個restful風格的處理層。彆着急!咱們立刻進一步改進它。函數
咱們知道restful風格強調面向資源操做。對於同一個資源,好比user表,咱們可能有增刪改查四種操做,按照以往的經驗,咱們可能會添加四個url, 並且 我猜測你們可能會像下面這樣設計(由於我就是這樣設計的,:-))——
get_user 獲取用戶信息
insert_user 添加用戶信息
update_user 修改用戶信息
delete_user 刪除用戶信息
但如今我以爲這樣設計有一些麻煩,每個表都要添加四個url,好煩,有沒有一個url解決全部問題呢?
答案固然是有,restful風格就幫咱們提供瞭解決思路。
restful 經過http請求方法區分不一樣操做,這樣咱們就能夠只請求同一個url,經過不一樣的請求方法達到區分增刪改查的方式,是否是很方便。
仍是剛纔的例子——user表,咱們能夠這樣設計
user
GET方法 獲取用戶信息
POST方法 添加用戶信息
PUT方法 修改用戶信息
DELETE方法 刪除用戶信息
瞭解了這些,咱們來看看剛添加的這個中間層該如何修改?
defined('BASEPATH') OR exit('No direct script access allowed'); /** * restful 核心類 * @class rest * extends CI_Controller */ class rest extends CI_Controller{ //請求對象 private $request; /** * 構造函數 */ public function __construct() { parent::__construct(); $this->request = new stdClass(); $this->request->method = $this->which_method(); } /** * 路由分配函數 */ public function _remap($method) { if(method_exists($this, $method.'_'.$this->request->method)){ call_user_func_array(array($this, $method.'_'.$this->request->method), array()); }else{ show_404(); } } /** * 解析http請求方式 */ protected function which_method() { $method = NULL; if(empty($method)) { $method = $this->input->method(); } return $method; } }
在上面的代碼中,咱們增長了兩個方法和一個屬性,分別爲_remap()、which_method 和 $request
他們各自的做用以下:
**_remap($method) ** CI內部方法,做用控制器重定向。
在控制器中重寫此方法後,那麼不管 URI 中包含什麼參數時都會調用該方法。
具體使用規範請查閱CI官方文檔https://codeigniter.org.cn/user_guide/general/controllers.html?highlight=_remap
咱們使用_remap() 來從新定義路由規則。
** which_method() **用來識別HTTP請求方式,這裏咱們使用了CI內部的Input輸入類提供的method方法來獲取HTTP請求方式並返回。
**$request **屬性用來記錄HTTP請求方式 方便全局調用,這裏咱們使用了PHP保留對象stdClass,它沒有具體含義,關於stdClass的使用方法請查閱官方文檔,這裏不做過多講解。
到此咱們的中間層初建模型,讓咱們來試試怎麼使用它。
首先,咱們在system/CodeIgnite.php 中添加一行,用來初始化咱們的中間層
//找到 &get_instance() 在其下面添加 if (file_exists(APPPATH.'core/rest.php')) { require_once APPPATH.'core/rest.php'; }
以後,咱們在application/controller中添加一個控制器User.php
defined('BASEPATH') OR exit('No direct script access allowed'); /* * restful 核心類 * @class rest * extends CI_Controller */ class user extends rest{//注意此處要繼承咱們的中間層 /* * 構造函數 */ public function __construct() { parent::__construct();//注意此處要執行父類構造方法 } public function user_get() { echo '執行了get方法'; } public function user_post() { echo '執行了post方法'; } public function user_put() { echo '執行了put方法'; } public function user_delete() { echo '執行了delete方法'; } }
到此,咱們能夠訪問URL http://host/user/user 試試咱們的改形成果了。
如今咱們已經能夠正確的分配路由了,下一篇咱們增長一些請求參數處理已經返回格式化方面的內容。
具體項目代碼請參考 https://github.com/lifeofmine/CI_RESTFUL/blob/master/front/application/core/MY_restful.php