2012-03-02 60 views
2

我有一個MySQL列'公共',其中包含布爾值(aka tinyint,1或0)。查詢時我通常不關心公共列的價值,所以默認情況下我會傳遞一個下劃線(MySQL通配符)。在某些情況下,儘管我只希望匹配「public = 0」或「public = 1」的行,所以我用0或1覆蓋下劃線。這不是我給出的最清晰的解釋,因此這裏是一些代碼:綁定「真或假」作爲PDO參數

public function get_hunts($public = '_') { 
    $sth = $this->_db->prepare("SELECT * FROM hunts WHERE(user_id = :user AND public = :public)"); 
    $sth->bindParam(':user', $this->_id); 
    $sth->bindParam(':public', $public); 
    $sth->execute(); 
    $result = $sth->fetchAll(PDO::FETCH_ASSOC); 

    return $result; 
} 

//get any result 
get_results(); 

//get only public results 
get_hunts(1) 

以這種方式綁定下劃線(我也嘗試了通配符%)導致查詢失敗。什麼是實現這一目標的更好方法?

回答

3

要使用任何通配符,你需要使用LIKE比較,而不是一個等於

AND public LIKE :public 

否則,你需要採取某種查詢生成器辦法,你建立的WHERE條件基於你的函數的參數。

public function get_hunts($public = null) { 
    $where = array(
     'user_id = :user' 
    ); 
    $params = array(
     ':user' => $this->_id 
    ); 

    if (null !== $public) { 
     $where[] = 'public = :public'; 
     $params[':public'] = (boolean) $public; 
    } 

    $query = 'SELECT * FROM hunts WHERE ' . implode(' AND ', $where); 
    $sth = $this->_db->prepare($query); 
    $sth->execute($params); // same as binding 

    return $sth->fetchAll(PDO::FETCH_ASSOC); 
} 
3

綁定參數僅供簡單的文字,所以你不能綁定之類的表和列名(標識)或IN條款(文字列表)。

所以你想要的是不可能以直接的方式。

你真的應該做的是使用不同的查詢:

function get_hunts($public=null) { 
    // assuming hunts.public is defined as NOT NULL 
    $sql = "SELECT * FROM hunts WHERE user_id=:user"; 
    if ($public!==null) { 
     $sql .= ' AND public=:public'; 
    } 
    $sth = $this->_db->prepare($sql); 
    $sth->bindParam(':user', $this->_id); 
    if ($public!==null) { 
     $sth->bindParam(':public', $public, PDO::PARAM_INT); 
    } 
    $sth->execute(); 
    return $sth->fetchAll(PDO::FETCH_ASSOC); 
} 

如果你真的不想使用不同的查詢,您可以使用一個哈克的解決方案與CASE表達。

SELECT * FROM hunts WHERE user_id=:user 
    AND public= 
    CASE :public WHEN 0 THEN 0 WHEN 1 THEN 1 ELSE public END 

如果綁定的值不是0或1,條件WHERE將需要public爲等於本身,因此總是正確的。否則使用:public的值。

+0

感謝您深思熟慮的答案。現在我只是用Phil的建議換成「public =:public」作爲「public LIKE:public」,允許我使用通配符;純粹是因爲它是一個快速和簡單的修復。儘管你的答案和菲爾的更長時間的選擇都可能是更好的解決方案,所以我學到了一些東西。 – MartinAnsty 2012-03-02 02:22:35

+0

+1好用'CASE' :)。僅供參考,你的第二個':user'綁定應該是':public' – Phil 2012-03-02 03:20:43

+0

@MartinAnsty它沒有被建議。你從懶惰和無知中選擇錯誤的解決方案 – 2012-03-03 08:28:08