Связывание «истина или ложь» в качестве параметра PDO - PullRequest
2 голосов
/ 02 марта 2012

У меня есть 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)

Привязка подчеркивания (я также пробовал общий подстановочный знак%) таким образом приводит к сбою запроса. Как лучше достичь этого?

Ответы [ 2 ]

3 голосов
/ 02 марта 2012

Параметры привязки предназначены только для простых литералов , поэтому вы не можете связывать такие вещи, как имена таблиц и столбцов (идентификаторы) или 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.

3 голосов
/ 02 марта 2012

Чтобы использовать любые символы подстановки, вам нужно использовать сравнение 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...