绑定”;真或假”;作为PDO参数


Binding "true or false" as a PDO parameter

我有一个MySQL列'public',它包含布尔值(也称为tinyint、1或0)。查询时,我通常不关心公共列的值,所以默认情况下我会传递一个下划线(MySQL通配符)。但在某些情况下,我只希望行与"public=0"或"public=1"匹配,所以我用0或1覆盖下划线。这不是我给出的最清晰的解释,所以这里有一些代码:

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)

以这种方式绑定下划线(我也尝试过通用通配符%)会导致查询失败。实现这一目标的更好方法是什么?

要使用任何通配符,您需要使用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);
}

绑定参数仅适用于简单文字,因此不能绑定表和列名(标识符)或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等于自身,因此始终为true。否则使用:public的值。