[CodeIgniter] 我的膝蓋被 CI 射了一箭之談 Input Class 的 get_post 方法需要注意的地方

今天一個正在進行中的案子,接到開發伙伴來的訊息,說他用POST來的資料,進去資料庫都是空白。看到這個訊息,我的心頭小鹿禁不住一陣亂撞,這下不得了,趕快測試看看:Model寫入資料庫沒問題,Controller丟資料給Model沒問題,難道是接收POST資料有問題?

於是趕緊打開心愛的Notepadd++看看程式,由於我是負責寫API接收Client丟資料來處理,然後回傳處理結果,而且Client端有可能用GET也可能用POST丟來,資料欄位多少不一定(這是我們訂好的規格),所以接收資料我是這樣寫的:

$data_array = $this->input->get_post(NULL,TRUE);

這樣我可以接收整個POST資料或GET資料,而且CI會幫我把整個$_POST或$_GET陣列過濾掉XSS然後傳回陣列給我。至於順序呢,依照CI的官方手冊說,它會先看POST再看GET。好了,這時候我們一般人的理解應該就是:如果有POST資料,它就用POST,然後傳回給我,如果沒有POST,它會再去看GET,然後一樣處理好傳回給我。

但,真的是這樣嗎? 當我單獨用$this->input->get(NULL,TRUE)或$this->input->post(NULL,TRUE)都沒問題,可以正常接收到整個GET或POST來的陣列,但是get_post這樣用就挫賽了。舉個例子,譬如我的某個API的URL點是這樣的:

http://api.example.com/v1/user/add

他可以接受POST或GET丟任意數量的資料來,我就接收起來,處理好存入資料庫。好了,如果Client端是這樣丟來的:

http://api.example.com/v1/user/add?token=9c6b99753ff8c41cda0331d634d2a4eac8e53a34

然後POST內容是這樣

name=David+Pai&mobile=0999123456

那這樣透過$this->input->get_post(NULL,TRUE)會得到什麼呢? 你以為$data_array會是這樣:

結果不是,只剩下這樣:

只剩下GET來的資料,POST全都不見了。

怎麼會這樣,不是說會先看POST再看GET,那至少給我POST資料吧,怎麼反而只給GET資料呢? 好的,這是我的膝蓋第一次被CI射了一箭,直到我去追了Input Class的原始碼…讓我們看看get_post這個方法:

看出來了嗎? 這下真相終於大白,如果你這樣用$this->input->get_post(NULL,TRUE),它會因為$_POST[NULL]判斷為false而直接跑去用$this->get(NULL,TRUE),所以得到的結果就只剩下GET來的東西了。

所以,對於CI的get_post,有幾個地方要注意:

  • 它沒有像get或post那樣,第一個參數指定為NULL就可以處理整個$_POST或$_GET
  • 如果第一個參數指定為NULL,只會得到跟get一樣的結果
  • 如果要像手冊說的那樣,第一個參數一定要指定

那麼,如果要像上面那個例子那樣,我POST和GET都要接收,然後碰到相同的以POST為先,這樣怎麼做呢? 既然CI沒有這樣的方法,那我們只好自力救濟啦,分開來接,然後再自己merge囉:

於是,這個Bug解決了,而我的膝蓋也復原了…

參考資料
CI官方手冊對於Input Class的說明

在〈[CodeIgniter] 我的膝蓋被 CI 射了一箭之談 Input Class 的 get_post 方法需要注意的地方〉中有 4 則留言

    • 呵呵,其實我平常也都是指定name接收的,只是碰到這個案子特殊,name是不知道的情況下才會這樣用
      套您的話,我也透過這次學習了^^

      回覆

發佈回覆給「davidpai」的留言 取消回覆