簡體   English   中英

PDO綁定問題

[英]PDO Binding Issue

我給出了給定代碼的以下SQL錯誤。

您的SQL語法有錯誤; 查看與您的MySQL服務器版本相對應的手冊,以便在第1行的''附近使用正確的語法

編碼:

$set_query = "";

foreach ($passed_columns as $c)
{
    $set_query .= $c . " = " . ':' . $c . ',';
}

$p = strlen($set_query);
$set_query[$p-1] = "";

$SQL = 'UPDATE users SET ' . $set_query . ' WHERE user_id IN (' . implode(",", $_POST['user_id']) . ')';

$stmt = $dbh->prepare($SQL);

foreach($_POST['cols'] as $key => $val)
{
    $stmt->bindValue(':' . $key, $val);
}

if (!$stmt->execute()) {
    die(print_r($stmt->errorInfo()));
}

$ _POST ['cols']包含一個鍵值數組(column_name => new column value)。 $ passed_columns只包含一個與$ _POST ['cols']中的鍵匹配的列名數組

我認為這個問題與價值觀的約束方式有關。 如果我回顯$ SQL變量,則輸出是有效的SQL(帶有我正在測試的值)。

但奇怪的是,如果我手動將$ SQL設置為有效的SQL,它只輸出(“UPDATE users SET role =:role WHERE user_id IN(100)”),腳本可以工作。

反饋:

  • 使用"string" . $var "string" . $var很快就變得難以理解了。 PHP可以直接在字符串中嵌入變量: "string $var"如果你需要做數組表達式,你可以使用大括號,如"string {$arr['key']}"

  • 我建議使用反向標記來分隔列名稱。

  • 從列表中刪除最后一個逗號是笨拙的。 最好將set-list構建為數組並使用逗號進行內爆。

  • 您的IN列表容易受到SQL注入攻擊。 使用(int)映射user_id值以刪除可能的惡意內容。 如果USER_ID值不是整數,然后使用查詢參數(但不要混用?使用命名參數的位置參數在單個語句-它混淆了PDO)。

  • bind_param()是不必要的。 只需將參數值傳遞給execute()即可。 在現代版本的PHP中,鍵值中的前導冒號是不必要的,這使得直接從鍵/值數組傳遞參數變得更加簡單。

  • 從您的示例中不清楚$ passed_columns是從用戶輸入中獲取的內容,還是在應用程序中硬編碼的內容。 小心以這種方式引入SQL注入。 我假設$ passed_columns只包含你控制的值。

  • prepare()在出錯時返回false ,因此您應該始終檢查其返回值並適當地響應錯誤。

  • print_r()實際打印到輸出,而不是返回一個字符串,除非你傳遞可選的第二個參數為true。

  • 這對大多數PHP開發人員來說都是一個驚喜,但雙引號字符串實際上比單引號字符串略快。 不管是差異都很小,但是雙引號字符串允許你將變量直接放在字符串中,為什么不呢?

以下是我編寫代碼的方法:

$set_terms = array();
foreach ($passed_columns as $c)
{
    $set_terms[] = "`$c` = :$c";
}
$set_clause = implode(",", $set_terms);

$user_id_list = implode(",", array_map(function($id) { return (int) $id; },
  $_POST["user_id"]);

$SQL = "UPDATE users SET {$set_clause} WHERE user_id IN ({$user_id_list})";

if (!($stmt = $dbh->prepare($SQL)) {
    die(print_r($dbh->errorInfo(), true));
}

if (!$stmt->execute($_POST["cols"])) {
    die(print_r($stmt->errorInfo(), true));
}

PS:如果你收到錯誤,只使用die()可能不是最好的事情。 專業的Web界面會為開發人員記錄錯誤,然后為用戶提供更好的屏幕。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM