PDO bindParam成一个语句?

时间:2011-04-16 02:52:44

标签: php mysql pdo

有没有办法将这些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网站上,它以单独的行显示它们,在所有示例中,我都看到它是在单独的行上。

有可能吗?

5 个答案:

答案 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简化为一行。