2011-04-16 68 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...)); 

先前已經消毒的,當然值將任何東西。