2014年1月15日 星期三

yii framework - 使用find、findByPk、findAll、findAllByPk的注意事項

查詢資料庫可以分為查(回傳) 一或是全部資料兩種, 可用的方式如下:


find() //查找指定條件的單個活動記錄。
findByAttributes() //查找具有指定屬性值的單個活動記錄。
findByPk() //查找指定主鍵的單一活動記錄。
findBySql() //查找指定SQL語句的單個活動記錄。


findAll() //查找滿足指定條件的所有活動記錄。
findAllByAttributes() //查找具有指定屬性值的所有活動記錄。
findAllByPk() //查找指定主鍵的所有活動記錄。
findAllBySql() //查找指定SQL語句的所有活動記錄。


我們來進一步看一下官方的code:



先看看findByPk, 這東西放在CActiveRecord.php裡 (我怎麼知道? 查這裡就有了)

public function findByPk($pk,$condition='',$params=array())
{
        Yii::trace(get_class($this).'.findByPk()','system.db.ar.CActiveRecord');
        $prefix=$this->getTableAlias(true).'.';
        $criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params,$prefix);
        return $this->query($criteria);
}



再找一下getCommandBuilder是什麼東東吧!

原來就是CDbCommandBuilder, 檔案是CDbCommandBuilder.php, 進一步查它的createPkCriteria:

public function createPkCriteria($table,$pk,$condition='',$params=array(),$prefix=null)
{
        $this->ensureTable($table);
        $criteria=$this->createCriteria($condition,$params);
        if($criteria->alias!='')
                $prefix=$this->_schema->quoteTableName($criteria->alias).'.';
        if(!is_array($pk)) // single key
                $pk=array($pk);
        if(is_array($table->primaryKey) && !isset($pk[0]) && $pk!==array()) // single composite key
                $pk=array($pk);
        $condition=$this->createInCondition($table,$table->primaryKey,$pk,$prefix);
        if($criteria->condition!='')
                $criteria->condition=$condition.' AND ('.$criteria->condition.')';
        else
                $criteria->condition=$condition;

        return $criteria;
}

簡單的說呢, 假如你打$raw=food::model()->findByPk(5);

那它就會先幫你找出你的food資料表裡面的主鍵(primaryKey)是什麼, 然後再用你輸入的值去查詢.

假如你的主鍵是foodID, 那它就會以foodID=5的方式去查, 就是這樣.

你會發現如果你沒有跟他說你的$params是什麼的話, 它就不會做預處理的 (參考這篇), 所以容易有SQL injections的問題.



總結一下:

無論是用哪個方式查, 一定要記得用$params綁定SQL 語句的參數, 這樣比較安全. 個人覺得如果你的查詢沒有很複雜的話, 可以使用之前說的compare方式, 方便、好記又安全, 而且寫出來的code也比較漂亮, 可以參考看看.

沒有留言:

張貼留言