PDO bindParam в одно утверждение?
Есть ли способ, которым я могу поместить эти операторы bindParam в один оператор?
$q = $dbc -> prepare("INSERT INTO accounts (username, email, password) VALUES (:username, :email, :password)");
$q -> bindParam(':username', $_POST['username']);
$q -> bindParam(':email', $_POST['email']);
$q -> bindParam(':password', $_POST['password']);
$q -> execute();
Я использовал mysqli, подготовленный раньше, где это было возможно, я переключился на PDO для поддержки assoc_array. На веб-сайте php.net для PDO он показывает их по отдельным строкам, и во всех примерах я видел, что он находится на отдельных строках.
Возможно ли это?
Ответы
Ответ 1
Пример 2 на странице execute
- это то, что вы хотите:
$sth->execute(array(':calories' => $calories, ':colour' => $colour));
Возможно, вам захочется посмотреть и на другие примеры. С параметрами вопросительных знаков это будет:
$q = $dbc -> prepare("INSERT INTO accounts (username, email, password) VALUES (?, ?, ?)");
$q->execute(array($_POST['username'], $_POST['email'], $_POST['password']));
Если это единственные столбцы, вы можете просто написать:
$q = $dbc -> prepare("INSERT INTO accounts VALUES (?, ?, ?)");
$q->execute(array($_POST['username'], $_POST['email'], $_POST['password']));
Ответ 2
Вспомогательная функция - это функция, которая помогает избежать написания букета повторяющегося кода каждый раз, когда вы хотите запустить запрос.
Это называется "программирование", и на этом сайте почти нет его, по крайней мере, в теге "PHP".
Хотя многие люди полагают, что программирование означает копирование/склеивание кусков кода из ручных примеров, оно несколько отличается.
Хотя трудно учиться, но действительно стоит того, особенно если вы посвящаете себя веб-разработке.
Как вы можете видеть, ни один принятый ответ не помог вам, поскольку вам все равно нужно написать что-то вроде
$sth->execute(array(':username' => $_POST['username'],
':email' => $_POST['email']
':password' => $_POST['password']);
столько раз, сколько полей в вашей таблице, что не сильно отличается от вашего первоначального подхода, все равно заставляет вас писать каждое имя поля в четыре раза.
Но будучи программистом, вы можете использовать возможности программирования. A цикл, например, один из операторов программирования в краеугольном камне.
Каждый раз, когда вы видите повторения, вы знаете, что должен быть цикл.
например, вы можете настроить список полей, называя их только один раз.
И пусть программа сделает все остальное.
Скажем, такая функция, как эта
function pdoSet($fields, &$values, $source = array()) {
$set = '';
$values = array();
if (!$source) $source = &$_POST;
foreach ($fields as $field) {
if (isset($source[$field])) {
$set.="`$field`=:$field, ";
$values[$field] = $source[$field];
}
}
return substr($set, 0, -2);
}
задается массив имен полей, он может создавать для вас как инструкцию insert, так и массив данных. Программный. Итак, ваш код станет не более, чем этими тремя короткими строками:
$fields = array('username', 'email', 'password');
$stmt = $dbh->prepare("INSERT INTO accounts SET ".pdoSet($fields,$values));
$stmt->execute($values);
Ответ 3
Ваше общее чувство совершенно верно, что целью кодирования является сохранение набора текста... но его решение не помогает бит BindParams. Я ничего не мог найти об этом в Интернете, поэтому вот что-то, что я, наконец, просто уговорил работать - надеюсь, это полезно для кого-то!
//First, a function to add the colon for each field value.
function PrepareString($array){
//takes array (title,author);
//and returns the middle bit of pdo update query :title,:author etc
foreach($array as $k =>$v){
$array[$k]=':'.$v;
}
return implode(', ', $array);
}
Тогда...
function PdoInsert($table_name,$array){
$db = new PDO(); //however you create your own pdo
//get $fields and $vals for statement
$fields_vals=array_keys($array);
$fields=implode(',',$fields_vals);
$vals=PrepareString($fields_vals);
$sql = "INSERT INTO $table_name($fields) VALUES ($vals)";
$qwe=$db->prepare($sql);
foreach ($array as $k =>$v ){
//add the colon to the key
$y=':'.$k;
//god knows why it doesn't like $qwe->bindParam($y,$v,PDO::PARAM_STR);
// but it really doesn't! So we refer back to $array.
//add checks for different binding types here
(см. PDO:: PARAM_INT важно в bindParam?)
$qwe->bindParam($y,$array[$k],PDO::PARAM_STR);
}
if ($qwe->execute()==true){
return $db->lastInsertId();
}
else {
return $db->errorCode();
}
}
Затем вы можете вставить что-либо, выполнив
PdoInsert('MyTableName',array('field1'=>$value1,'field2'=>$value2...));
Предварительно дезинфицировали ваши ценности.
Ответ 4
+1 Мэтью Флашен за принятый ответ, но я покажу вам еще один совет. Если вы используете параметры SQL с именами так же, как и записи в $_POST, вы можете воспользоваться тем фактом, что $_POST уже является массивом:
$q->execute($_POST);
Имена параметров SQL имеют префикс двоеточия (:
), но ключи в массиве $_POST не являются. Но современные версии PDO учитывают это - вам больше не нужно использовать префиксы двоеточия в ключах в массиве, который вы передаете для выполнения().
Но вы должны быть осторожны, чтобы каждый мог добавить дополнительные параметры в любой веб-запрос, и вы должны получить только подмножество параметров $_POST, которые соответствуют параметрам в вашем запросе.
$q = $dbc -> prepare("INSERT INTO accounts (username, email, password)
VALUES (:username, :email, :password)");
$params = array_intersect_key($_POST, array("username"=>1,"email"=>1,"password"=>1));
$q->execute($params);
Ответ 5
Лично я предпочитаю использовать функцию-обертку для всех pdo, что существенно упрощает необходимый код.
Например, чтобы запускать связанные запросы (ну, все мои запросы), я делаю это:
$iterable_resultset = query("INSERT INTO accounts (username, email, password) VALUES (:username, :email, :password)", array(':username'=>'bob', ':email'=>'[email protected]', ':password'=>'bobpassword'));
Обратите внимание, что не только sql просто строка, но и фактически многократно используемая строка, поскольку вы можете просто передать sql в виде строки и изменить массив переменных, которые нужно передать, если вы хотите выполнить аналогичную вставку сразу после что один (не применим к этой ситуации, но применим к другим случаям использования sql).
Код, который я использую для создания этой функции-обертки, приведен ниже:
/**
* Run bound queries on the database.
*
* Use: query('select all from players limit :count', array('count'=>10));
* Or: query('select all from players limit :count', array('count'=>array(10, PDO::PARAM_INT)));
*
* Note that it returns foreachable resultset object unless an array is specifically requested.
**/
function query($sql, $bindings=array(), $return_resultset=true) {
DatabaseConnection::getInstance(); // Gets a singleton database connection
$statement = DatabaseConnection::$pdo->prepare($sql); // Get your pdo instance, in this case I use a static singleton instance. You may want to do something simpler.
foreach ($bindings as $binding => $value) {
if (is_array($value)) {
$first = reset($value);
$last = end($value);
// Cast the bindings when something to cast to was sent in.
$statement->bindParam($binding, $first, $last);
} else {
$statement->bindValue($binding, $value);
}
}
$statement->execute();
if ($return_resultset) {
return $statement; // Returns a foreachable resultset
} else {
// Otherwise returns all the data an associative array.
return $statement->fetchAll(PDO::FETCH_ASSOC);
}
}
// Wrapper to explicitly & simply get a multi-dimensional array.
function query_array($sql_query, $bindings=array()) {
return query($sql_query, $bindings, false); // Set return_resultset to false to return the array.
}
Как отмечено в комментариях, вы хотите использовать свой собственный метод для настройки соединения с базой данных и получения инициализированного pdo, но в общем случае он позволяет сократить ваш SQL-код до одной строки.