有時候在一些比較老的系統中做開發,用的thinkphp3.2架構。
不得不說,thinkphp有它的優點 ,但也發現了不少缺陷。比如今天說的,就是進行sql查詢時的bug。
thinkphp支援where函數傳入查詢條件,當我要查詢id在,或者不在一些數組裡面的時候,代碼可以這麼寫:
$ids = array();
$data = M('User')->where(array(
'id'=>array('not in',$ids)
))->select();
注意,這裡的$ids是一個空數組。這種情況,無論是not in,還是in,thinkphp拼裝出來的sql是這樣的:
SELECT * FROM `user` WHERE `id` NOT IN () ;
而這樣的sql語句運作是會報錯的。作為一個架構,在傳入參數都合法的情況下,竟然生成一條報錯的sql,實在是不應該。
正确的SQL應該是這樣的:
SELECT * FROM `user` WHERE `id` NOT IN ('') ;
是以,我對ThinkPhp3.2架構的DB層進行了簡單的修改。
在Common/ThinkPHP/Library/Think/Db/Driver.class.php的parseWhereItem方法裡,可以找到這樣的代碼:
}elseif(preg_match('/^(notin|not in|in)$/',$exp)){ // IN 運算
if(isset($val[2]) && 'exp'==$val[2]) {
$whereStr .= $key.' '.$this->exp[$exp].' '.$val[1];
}else{
if(is_string($val[1])) {
$val[1] = explode(',',$val[1]);
}
$zone = implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.$this->exp[$exp].' ('.$zone.')';
}
}
我簡單的修改後,變成了:
}elseif(preg_match('/^(notin|not in|in)$/',$exp)){ // IN 運算
if(isset($val[2]) && 'exp'==$val[2]) {
$whereStr .= $key.' '.$this->exp[$exp].' '.$val[1];
}else{
if(is_string($val[1])) {
$val[1] = explode(',',$val[1]);
}
$zone = implode(',',$this->parseValue($val[1]));
if(empty($zone)){
$whereStr .= $key.' '.$this->exp[$exp].' (\'\')';
}else{
$whereStr .= $key.' '.$this->exp[$exp].' ('.$zone.')';
}
}
}
這樣,即使傳入一個空數組,也不會報錯,而且還會傳回你想要的查詢結果。