Mybb1.6升級到1.8升級的過程中,遇到問題無數,近日發現了一個Mybb1.8資料庫核心操作update_query的程式碼中存在嚴重bug,導致資料存入時漏掉前面的零,折騰數小時,發現錯不在俺,而在mybb的升級代碼。
資料表:test
欄位
ID int(10) AUTO_INCREMENT
name varchar(60) not null
category varchar(5)
在此表中category來表示分類,分類釆用常見的代碼表示,共五位數字,前二位0l一99表示大類,後三位表示小類。在更新語句中透過Ajax提文更新,在台後語句中透過update_query更新資料。程序在1·6時工作正常,在開級1·8時更新混亂,檢查下來發現category字段前面的“0”丟失。透過變化各種手段均不能解決問題。最後把Mybb的資料操作核心檔翻出來,比較其1.6版本發現程式碼有低階bug,導致錯誤發生。
下面是1.8版数据更新过程
Php代码
function update_query($table, $array, $where="", $limit="", $no_quote=false) { global $mybb; if(!is_array($array)) { return false; } $comma = ""; $query = ""; $quote = "'"; if($no_quote == true) { $quote = ""; } foreach($array as $field => $value) { if(isset($mybb->binary_fields[$table][$field]) && $mybb->binary_fields[$table][$field]) { if($value[0] != 'X') // Not escaped? { $value = $this->escape_binary($value); } $query .= $comma."`".$field."`={$value}"; } else { if(is_numeric($value)) { $query .= $comma."`".$field."`={$value}"; } else { $query .= $comma."`".$field."`={$quote}{$value}{$quote}"; } } $comma = ', '; } if(!emptyempty($where)) { $query .= " WHERE $where"; } if(!emptyempty($limit)) { $query .= " LIMIT $limit"; } return $this->write_query(" UPDATE {$this->table_prefix}$table SET $query "); }
而1.6版本是这样的
Php代码
function update_query($table, $array, $where="", $limit="", $no_quote=false) { if(!is_array($array)) { return false; } $comma = ""; $query = ""; $quote = "'"; if($no_quote == true) { $quote = ""; } foreach($array as $field => $value) { $query .= $comma."`".$field."`={$quote}{$value}{$quote}"; $comma = ', '; } if(!emptyempty($where)) { $query .= " WHERE $where"; } if(!emptyempty($limit)) { $query .= " LIMIT $limit"; } return $this->write_query(" UPDATE {$this->table_prefix}$table SET $query "); }
发生错误的是这样几句
Php代码
if(is_numeric($value)) { $query .= $comma."`".$field."`={$value}"; } else { $query .= $comma."`".$field."`={$quote}{$value}{$quote}"; }
传过来category的值可能是01002或08003,只要is_numeric($value)为真就是数字类型?!这是什么逻辑。其时mysql能自动处理识别字符型和数字型的差别,升级的1.8版把简单的事情复杂化,错误的逻辑导致bug发生,导致传过来的由数字组成的字符串存入数据库时前面的0丢失。如果前面不为0,就不会出错,这样导致数据一片混乱。
一直以来很欣赏Mybb简洁的代码和漂亮的系统架构,2M代码包括图片CSS等竟然能完成如此多的功能,给予用户良好的扩展能力。没想到翻出这样一个bug,见笑了。1.6至1.8改动很大,发布过于仓促。总体说来,Mybb不失一个漂亮简洁的php论坛。