2011-04-16 94 views
13

有没有一种方法可以将这些bindParam语句放入一个语句中?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网站上,它将在单独的行中显示它们,并且在所有示例中我都看到它在单独的行中。

可能吗?

+0

for assoc_array支持?你不是指指定的占位符吗? – 2011-04-16 03:10:37

+0

只是好奇,你会用这种方式吗?没有帮手功能等? – 2011-04-16 03:22:28

+0

我今天才刚刚开始使用PDO,如果您愿意解释,我不知道辅助函数是什么? – Basic 2011-04-16 03:42:12

回答

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'])); 
+0

谢谢你,这也是最后一个问题,我有一个SELECT查询,它只需要一个占位符:email,最好是将它存储在一个数组中,将bindParam的代码行从等式中移除,但数组只会存储1个变量,因为我只有一个占位符:电子邮件,哪个更好? – Basic 2011-04-16 03:09:27

+0

@Basic,我倾向于使用数组。我也更喜欢?占位符。但是,两者都是主观的。 – 2011-04-16 03:14:49

4

辅助函数是一个功能,让你有助于避免重复写一堆每次要运行查询时都要编码。
这就是所谓的“编程”,在这个网站上几乎没有,至少在“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); 
} 

这样的功能被赋予的字段名称的数组,它可以产生两种插入语句,并为您的数据阵列。编程。所以,你的代码变得不超过这3个短线更多:

$fields = array('username', 'email', 'password'); 
$stmt = $dbh->prepare("INSERT INTO accounts SET ".pdoSet($fields,$values)); 
$stmt->execute($values); 
+0

真棒回答!我会尝试这:)而且我从不复制和粘贴,但我在梯子上的几个梯级比你低atm:p – Basic 2011-04-16 09:45:04

+0

如果你使用'''占位符,你根本不需要重复字段名称,我*提到了(以及我推荐的示例中显示了哪个)。 – 2011-04-16 23:58:32

+1

@Matthew'?'占位符只是FOUR的一个地方。请不要在评论中浪费时间。在REAL LIFE代码中生成简洁和可用的代码片段就足够了。 – 2011-04-17 15:43:41

1

就个人而言,我更喜欢使用所有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被减少到只有一行。

3

+1给Matthew Flaschen接受的答案,但我会告诉你另一个提示。如果您使用的SQL参数与名称相同,$ _ POST条目,你可以利用的事实,$ _ POST已经是一个数组:

$q->execute($_POST); 

的SQL参数名前面有一个冒号(:)但$ _POST数组中的键不是。但是现代版本的PDO对此进行了说明 - 您不再需要在传递给您执行的数组中的键中使用冒号前缀()。

但是,您应该小心,任何人都可以为任何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

您的常识是完全正确的,编码的目的是保存打字......但他的解决方案并没有帮助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...)); 

先前已经消毒的,当然值将任何东西。