В моей базе данных у меня есть поля, такие как «статус» , которые являются зарезервированными ключевыми словами. Этот код отлично работает для меня ( статус экранируется “ ):
$sql = "UPDATE $table SET `status`='$status' WHERE `id`='123'";
Но теперь я хочу использовать только подготовленные заявления! Мой Database.class:
class Database extends \PDO { private $_sth; // statement private $_sql; public function update($tbl, $data, $where, $where_params = array()) { // prepare update string and query $update_str = $this->_prepare_update_string($data); $this->_sql = "UPDATE $tbl SET $update_str WHERE $where"; $this->_sth = $this->prepare($this->_sql); // bind values to update foreach ($data as $k => $v) { $this->_sth->bindValue(":{$k}", $v); } // bind values for the where-clause foreach ($where_params as $k => $v) { $this->_sth->bindValue(":{$k}", $v); } return $this->_sth->execute(); } private function _prepare_update_string($data) { $fields = ""; foreach ($data as $k => $v) { $fields .= "`$k`=:{$k}, "; } return rtrim($fields, ", "); } }
Пример обновления, который не будет работать:
$DB = new Database(); $DB->update("tablename", array("status" => "active"), "`username`=:username AND `status`=:status", array("username" => "foofoo", "status" => "waiting"));
Я думаю, это из-за ключевого слова reserverd «status». Но я не знаю, как избежать этого. Я попытался скрыть местозаполнитель в _prepare_update_string ($ data), чтобы:
bindValue("`:{$k}`", $v)
но результата нет.
Я надеюсь, что решение очень простое, и это просто застрявшее переполнение в моем мозгу. 😉 Спасибо заранее!
Когда вы строите строку SQL (prepare_update_string, я думаю), а также как в цикле foreach, где вы привязываете данные, запускайте увеличивающийся счетчик и добавляете его к значению привязки. Итак ": статус" станет ": status1".
Что-то вроде:
$i = 1; foreach ($data as $k => $v) { $this->_sth->bindValue(":{$k.$i}", $v); $i++; }
Это решит проблему любых зарезервированных ключевых слов.
Он также решает проблему (с которой я уверен, что вы столкнетесь в будущем), где вам нужно связываться с одним и тем же заполнителем более одного раза.
например, вместо следующего, который выдает ошибку из-за двух привязок на: place placeholder
SELECT * from table WHERE `status` = :status AND `otherfield` = :status
С увеличивающимся счетчиком это становится:
SELECT * from table WHERE `status` = :status1 AND `otherfield` = :status2
Наслаждаться.