有没有办法将这些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支持。在PDO的php.net网站上,它以单独的行显示它们,在所有示例中,我都看到它是在单独的行上。
有可能吗?
答案 0 :(得分:22)
execute
页面上的示例2是您想要的:
$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']));
答案 1 :(得分:4)
辅助函数是一个函数,可以帮助您在每次运行查询时避免编写大量重复代码。
这被称为“编程”,在这个网站上几乎没有,至少在“PHP”标签下
虽然许多人认为编程代表从手动示例中复制/粘贴代码块,但它有些不同。
虽然它很难学,但确实值得,特别是如果你正致力于网络开发。
正如你所看到的,没有接受的答案对你没有任何实际帮助,因为你仍然需要写一些像
$sth->execute(array(':username' => $_POST['username'],
':email' => $_POST['email']
':password' => $_POST['password']);
表中的字段数量与初始方法相差无几,仍然会让您每次写入每个字段名称。
但作为一名程序员,你可以使用编程的力量。例如,循环 - 基石编程运算符之一 每当你看到重复时,你就知道应该有一个循环。
例如,您可以设置字段列表,仅命名一次。 让一个程序完成其余的工作。说,像这样的功能
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语句和数据数组。编程。所以,你的代码不会超过这3条短线:
$fields = array('username', 'email', 'password');
$stmt = $dbh->prepare("INSERT INTO accounts SET ".pdoSet($fields,$values));
$stmt->execute($values);
答案 2 :(得分:4)
你的常识是完全正确的,编码的目的是节省打字......但他的解决方案对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 is important in 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...));
事先已经清理了你的价值观。
答案 3 :(得分:3)
+1给Matthew Flaschen接受的答案,但我会告诉你另一个提示。如果使用名称与$ _POST中的条目相同的SQL参数,则可以利用$ _POST已经是数组的事实:
$q->execute($_POST);
SQL参数名称以冒号(:
)为前缀,但$ _POST数组中的键不是。但现代版本的PDO解释了这一点 - 您不再需要在传递给execute()的数组中的键中使用冒号前缀。
但是你应该小心,任何人都可以为任何web请求添加额外的参数,你应该只获得与查询中的参数匹配的$ _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);
答案 4 :(得分:1)
就个人而言,我更喜欢为所有pdo使用包装函数,这大大简化了必要的代码。
例如,要运行绑定查询(以及我的所有查询),我这样做:
$iterable_resultset = query("INSERT INTO accounts (username, email, password) VALUES (:username, :email, :password)", array(':username'=>'bob', ':email'=>'bob@example.com', ':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简化为一行。