2017-03-09 103 views
-2

我正在研究一個應用程序,並且我正在更新MySQL數據庫表中的值。如何使用PHP更新MySQL表格從HTML表單準備語句

當我使用名稱屬性(即name="value1")的單值版本時,一切正常。但是,當我使用name屬性的數組語法(name="value[]")時,出現錯誤。

的錯誤就在這裏發生:

$stmt = $conn->prepare("UPDATE students SET value=value+{$_POST['value']}"); 

的錯誤是:

Error: Notice: Array to string conversion on line 8
Error: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'value' in 'field list'

這是我PDOStatement對象::執行聲明。

$stmt->execute(array("value", $_POST['value'])); 

這是我的HTML:

<input class="input" id="id1" name="value[]" type="range"> 
<input class="input" id="id2" name="value[]" type="range"> 
<input class="input" id="id3" name="value[]" type="range"> 

在我的表中的列被命名爲值1值2值3等。

+2

http://bobby-tables.com/ – GordonM

回答

0

警告:切勿直接從$ _POST使用任何東西! Sanitize驗證所有用戶輸入。您在下面看到的僅用於演示目的。在查詢中沒有WHERE子句,整個表將被更新。


當你做到這一點在你的HTML元素<input>

name="value[]" 

$_POST將收到的$_POST元素數組。因此,

$_POST['value'] //resolves to an array. 

這就是爲什麼你得到一個錯誤(錯誤:注意:數組字符串轉換),當你這樣做:

$stmt = $conn->prepare("UPDATE `students` SET `value` = `value` +{$_POST['value']}"); 

牙套{}期間內串插值通常用於雙引號。您的代碼試圖將數組轉換爲字符串。

你可能反而試試這個:

$stmt = $conn->prepare("UPDATE `students` SET `value1` = `value1` + ?"); 

或者,這...

$stmt = $conn->prepare("UPDATE `students` SET `value1` = `value1` + :value1"); 

不要把用戶直接輸入到一個事先準備好的聲明。 PHP PDO::prepare手冊頁狀態。

Prepares an SQL statement to be executed by the PDOStatement::execute() method. The SQL statement can contain zero or more named (:name) or question mark (?) parameter markers for which real values will be substituted when the statement is executed. You cannot use both named and question mark parameter markers within the same SQL statement; pick one or the other parameter style. Use these parameters to bind any user-input, do not include the user-input directly in the query.

您需要先對數組$_POST['values']進行一些處理。 消毒驗證的數據是非常明智和最佳實踐。

您的<input>元素的數據實際上就在這裏。

$_POST['values'][0] //Resolves to a string. 
$_POST['values'][1] //Resolves to a string. 
$_POST['values'][2] //Resolves to a string. 

錯誤柱未發現:在「字段列表」 1054未知列「值」建議你應該在你的表使用實際的列名。用你自己的話說,這些字段名稱是value1,value2value3

當您使用PDOStatement::execute,你可以這樣做只是爲了看看事情正在?方式工作....

$stmt->execute([$_POST['values'][0]])     //PHP 5.4+ 

或者

$stmt->execute(array([$_POST['values'][0]))    //PHP 5.3 and below 

如果使用命名參數,則可以試試這個。

$stmt->execute(['value1' => $_POST['values'][0]])  //PHP 5.4+ 

或者

$stmt->execute(array('value1' => [$_POST['values'][0])) //PHP 5.3 and below 

....但我認爲這種生活危險首先消毒並驗證您的輸入

如果你有機會使用MySQL stored procedures(比方說,對於電子商務網站)與您的PDO預處理語句的點,擡頭PDOStatement::bindParam(必須使用這個變量)和PDOStatement::bindValue(可以使用一般的值,比如字符串文字)。

$stmt->bindValue(1, $variable); 
$stmt->execute(); 

或者......

$stmt->bindValue(:name, $variable); 
$stmt->execute(); 

$stmt->bindParam(1, $variable);$stmt->bindParam(:name, $variable);是使用IN/OUT參數與存儲過程中最有用。

要小心。您將最終更新整個表格,因爲查詢中沒有WHERE條件!但是,如果您希望所有記錄具有相同的值,那麼您可以這樣做。 :-) Edgar F. Codd會說什麼?

儘管可以使用循環來解決使用全部三個假設的$ _POST ['value']元素的問題,但仍然需要問爲什麼整個表需要爲每次迭代更新。

我編輯了你的答案,看起來像這樣。

if(isset($_POST['value']) && is_array($_POST['value']) && !empty($_POST['value']) && (count($_POST['value']) === 3)){ 
    foreach($_POST['value'] as $key => $value) { 
     $num = ($key + 1); 
     $stmt = $conn->prepare("UPDATE `students` SET value{$num} = ? + value{$num}"); 
     $stmt->bindValue(1, $value); 
     $stmt->execute(); 
    } 
} 

雖然不全面,但至少有更好的檢查正在完成。但是,這樣的事情可能會更好。

if(!isset($_POST['value']) || !is_array($_POST['value']) || empty($_POST['value']) || (count($_POST['value']) !== 3)){ 
    throw new UnexpectedValueException("Something is wrong with the input in $_POST."); 
} 

foreach($_POST['value'] as $key => $value) { 
    $num = ($key + 1); 
    $stmt = $conn->prepare("UPDATE `students` SET value{$num} = ? + value{$num}"); 
    $stmt->bindValue(1, $value); 
    $stmt->execute(); 
} 
+0

PDO有這麼多選擇。 – Melinda

0

感謝您的全面反應。我沒有提到輸入必須增加數據庫值。但是,這是我如何使其工作。

if(isset($_POST['value'])){ 
    if(is_array($_POST['value'])) { 
    foreach($_POST['value'] as $key => $value) { 
    $stmt = $conn->prepare("UPDATE students SET value".($key+1)." = ? + value".($key+1)." "); 
    $stmt->execute(array($value)); 

    } 
} 

感謝那個取消了他的答案但他給了我靈感的人!

+0

您尚未篩選並驗證輸入。即使數組的索引都是用戶輸入(它們可以由用戶使用開發人員工具操作)。你做了太多的假設,完全違背了使用準備好的語句的目的。如果您一次創建了一個表達式$ tempVar = $ key + 1,則不必在每次迭代中重複三次加法操作。 –

+0

您可以使用'PDOStatement :: bindParam' /'PDOStatement :: bindValue,但不能與帶有參數的'PDOStatement :: execute'結合使用。它是一個或另一個。 –

+0

直接從$ _POST(即使使用循環)直接進入查詢並不是最佳實踐。 –