2013年12月24日 星期二

yii framework - 查詢資料大解密之"CDbCriteria到底是什麼"? (說明compare跟addCondition的差別)

先看看官方對CDbCriteria的解釋:

CDbCriteria represents a query criteria, such as conditions, ordering by, limit/offset. 

意思是

CDbCriteria代表查詢的條件、排序還有資料取得數目 (筆數)的上下限.

相信如果你爬了很多文會發現一件事, 就是當我們要做 "欄位=$讀取的變數"這樣的條件查詢時, 會出現compareaddCondition, 到底差在哪裡呢? 我們又要選擇哪個呢?

好, 我們來看看兩者的寫法

首先是compare

$target=$_POST['name'];
$criteria = new CDbCriteria;
$criteria->compare('name', $target);
$rawdb=某models的名字::model()->findAll($criteria);

再來是addCondition:


$target=$_POST['name'];
$criteria = new CDbCriteria;
$criteria->addCondition('name = :x');
$criteria->params=array(':x' => $target);
$rawdb=某models的名字::model()->findAll($criteria);

參考一下這個

一切的解答都在官方的Source Code點這裡

我先解釋一下兩者內部的Code到底在寫什麼

compare

public function compare($column, $value, $partialMatch=false, $operator='AND', $escape=true)
{
if(is_array($value))
{
       if($value===array())
               return $this;
       return $this->addInCondition($column,$value,$operator);
}
else
       $value="$value";

if(preg_match('/^(?:\s*(<>|<=|>=|<|>|=))?(.*)$/',$value,$matches))
{
       $value=$matches[2];
       $op=$matches[1];
}
else
       $op='';

if($value==='')
       return $this;

if($partialMatch)
{
       if($op==='')
               return $this->addSearchCondition($column,$value,$escape,$operator);
       if($op==='<>')
               return $this->addSearchCondition($column,$value,$escape,$operator,'NOT LIKE');
}
elseif($op==='')
       $op='=';

$this->addCondition($column.$op.self::PARAM_PREFIX.self::$paramCount,$operator);
$this->params[self::PARAM_PREFIX.self::$paramCount++]=$value;

return $this;

}

1. 當compare的$value參數是一個陣列array的時候改用"addInCondition"這個function

2. 用正規式來檢查$value裡有沒有符合比較運算子+字串 (就是不等於、小於等於、大於等於、小於、大於、等於這些鬼啦!) 的格式. 例如:<>大便, 就會變成$value=大便、 $op=<>

3. $partialMatch預設是false, 所以當傳來的是true的時候就會改用addSearchCondition這個function (也就是先前註解[4]說的模糊匹配).

-上面的$op是''的時候就是把資料庫的某欄位裡$value值的都抓出來
-上面的$op是<>的時候則是把資料庫的某欄位裡沒有$value值的都抓出來

4. 最後就是在$partialMatch預設是false的情況下使用addCondition這個function (也就是完全匹配, 一樣參考先前的註解[4])


addCondition:

public function addCondition($condition,$operator='AND')
{
if(is_array($condition))
{
       if($condition===array())
               return $this;
       $condition='('.implode(') '.$operator.' (',$condition).')';
}
if($this->condition==='')
       $this->condition=$condition;
else
       $this->condition='('.$this->condition.') '.$operator.' ('.$condition.')';
return $this;
}

addCondition就是把不同 (含有比較運算子)的字串用AND連接起來, 所以連續的使用addCondition就可以串成一個長的查詢字串, 例如:

$criteria->addCondition('id=1');
$criteria->addCondition('name=joer');
$criteria->addCondition('age=18');

這樣最後送到資料庫的時候就相當於sql裡的 where id='1' and name='joer' and age='18'

注意! addCondition沒有內建參數綁定. 所以在使用的時候才需要這樣寫:

$criteria->addCondition('name = :x');
$criteria->params=array(':x' => $target);

最後

就如這篇所說的, compare非常聰明, 幾乎囊括我們常用的條件, 並且會依我們下的比較運算子去使用不同的查詢function, 甚至會自已使用參數綁定-parameter binding , 所以結論應該出來了!

讓我們擁抱compare吧^^


補充:2013.12.25
也許有人會問compare這麼好, 那為什麼還要addCondition?
我想原因可能是:

1. compare是yii 在1.1版才有的功能, 所以保留有可能是為了相容之前開發者寫的code
2. 在比較運算子是固定的(不隨程式變動)+知道$value是什麼型態(例如:字串 or array)的情況下, 直接使用addCondition或是addInCondition, 甚至是addSearchCondition效能會比較好?(沒實際測試過), 不過compare可以讓開發者少寫一些code讓整個程式更簡潔, 以及對之後程式的調整適應力更強的情況下, 我想還是會不少開發者會使用compare吧!

沒有留言:

張貼留言