CodeIgniter,自己覺得非常感動 XD,也非常欣慰,希望把好東西推廣給大家知道。廢話不多說,先來說說問題點,先前發表的一篇 [CodeIgniter] 利用 jQuery 簡易驗證使用者帳號/Email 最後有人留言針對 input->post() 在中文官網上面的 Input Class 教學有些疑慮,底下我先來說明網友的問題點。
input->post 如果為空,則塞進去資料庫竟然是 0 該網友引用了 Input Class 中文文件的內容
使用 POST, COOKIE, 或 SERVER 資料CodeIgniter 提供三個讓你取出 POST, COOKIE 或 SERVER 中項目的補助函數。使用這些函數的主要便利性在於, 它們會確認並檢視是否這些項目已被設定並且在未設定時回傳 false (boolean) , 而不是直接取出 ($_POST[‘something’]),官方範例↓這讓你可以方便地使用資料而不必預先測試它們是否存在。不然, 通常你可能會像這樣做:if ( ! isset($_POST[‘something’])) { $something = FALSE; } else { $something = $_POST[‘something’]; } 網友敘述:
但是為什麼還是為設定為0呢??這應該是檢查資料有沒有被設定而已,那我如果沒有輸入,又怎麼會出現 0 呢?? 網友希望 $username = $this->input-post(“username”); 能幫他判斷如果 username 沒有資料,就直接回傳 NULL,Insert 到資料庫時,應該是 NULL 而不是 0。
程式範例 網友其實沒有錯,根據文件上顯示,如果 $something =
$this->input->post(“something”); 取值過後,如果系統沒有 $_POST[‘something’],則會回傳 FALSE,我猜網友在跟 model 作搭配的時候使用了底下的寫法來塞值進入資料庫:
$data = array( "username" => $this->input->post('username'), "passwd" => $this->input->post('passwd'), "email" => $this->input->post('email'), ); $this->load->model('members'); $this->members->register($data);假設如果沒有 $_POST['email'] 的話,該欄位就會被設定為 0,原因很簡單,就是出在要塞值進入資料庫的時候,程式針對資料的型態判斷啦,底下從最開始取得
$_POST 資料開始說起。
Input Class 核心程式流程($_POST) 程式剛開始是這樣寫 $username = $this->input->post(“username”); 對應到系統
system/core/Input.php 程式裡面的 post method:
/** * Fetch an item from the POST array * * @access public * @param string * @param bool * @return string */ function post($index = NULL, $xss_clean = FALSE) { // Check if a field has been provided if ($index === NULL AND ! empty($_POST)) { $post = array(); // Loop through the full _POST array and return it foreach (array_keys($_POST) as $key) { $post[$key] = $this->_fetch_from_array($_POST, $key, $xss_clean); } return $post; } return $this->_fetch_from_array($_POST, $index, $xss_clean); }當你傳入 username 的參數,就會直接會被送到
$this->_fetch_from_array($_POST, $index, $xss_clean); 接著我們看 _fetch_from_array 這 private method
/** * Fetch from array * * This is a helper function to retrieve values from global arrays * * @access private * @param array * @param string * @param bool * @return string */ function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE) { if ( ! isset($array[$index])) { return FALSE; } if ($xss_clean === TRUE) { return $this->security->xss_clean($array[$index]); } return $array[$index]; }有看到程式會先判斷
$_POST[‘username’] 是否存在,如果不存在則回傳 FALSE,也就是先前的 $username 就會是個 bool 函數,其值是 FALSE,那接著我們來看看 Database 怎麼處理傳入的 Value 值,先到 system/database 打開 DB_driver.php,找到 Insert 資料庫的 method:
/** * Generate an insert string * * @access public * @param string the table upon which the query will be performed * @param array an associative array data of key/values * @return string */ function insert_string($table, $data) { $fields = array(); $values = array(); foreach ($data as $key => $val) { $fields[] = $this->_escape_identifiers($key); $values[] = $this->escape($val); } return $this->_insert($this->_protect_identifiers($table, TRUE, NULL, FALSE), $fields, $values); }會看到處理 value 是在
$values[] = $this->escape($val);,接著我們找到 escape 這 method:
/** * "Smart" Escape String * * Escapes data based on type * Sets boolean and null types * * @access public * @param string * @return mixed */ function escape($str) { if (is_string($str)) { $str = "'".$this->escape_str($str)."'"; } elseif (is_bool($str)) { $str = ($str === FALSE) ? 0 : 1; } elseif (is_null($str)) { $str = 'NULL'; } return $str; }有看到解答了嗎?關鍵就在 is_bool($str) 這判斷式,因為 $username 值為 FALSE,所以在這裡會被設定為 0,也就是為什麼網友會說資料庫欄位怎麼都是一堆 0,原因就是這樣啦,當然也不是沒有解法阿,其實解法很容易,只是自己還是要判斷一下:
$data = array( "username" => ($username) ? $username : NULL, "passwd" => ($passwd) ? $passwd : NULL, "email" => ($email) ? $email : NULL, );這樣就可以了
See also
- 來聊聊 PHP & JavaScript & CSS 的 Coding Style
- 為什麼我選擇使用 Laravel Framework?
- Laravel 搭配 Google, Facebook, Twitter 第三方 OAuth 認證
- 將 wordpress 強制使用 SSL 連線
- PHP 7 vs HHVM Benchmark 比較
- Laravel 50 個小技巧 + Laravel 5.2 新功能
- Laravel Homestead 支援 MySQL 5.7 和 Node 5.0
- PHP-FIG 新網站
- Laravel Homestead 支援 PHP 7
- Laravel 5.1 is released