3 回答

TA貢獻1811條經驗 獲得超4個贊
您不應該將表單字段作為列表重復name0
,name1
..name99
相反,您需要將它們作為數組發送,例如:data[0][name]
..data[99][name]
另外,最好使用 PHP 生成 HTML,以免違反DRY 規則,您會意識到將來何時需要使用重復字段編輯表單:
<!DOCTYPE html>
<html>
<head>
? ? <link rel="stylesheet" type="text/css" href="css/style.css">
? ? <meta charset="utf-8">
</head>
<body>
<form action="php/insert-multi-ing.php" method="POST">
? ? <table>
? ? ? ? <tr>
? ? ? ? ? ? <th>Nom Ingrédient</th>
? ? ? ? ? ? <th>Prix</th>
? ? ? ? ? ? <th>Prix Ingrédient</th>
? ? ? ? ? ? <th>Quantite Ingrédient</th>
? ? ? ? ? ? <th>Unite</th>
? ? ? ? </tr>
? ? ? ? <?php
? ? ? ? for ($i = 0; $i < 10; $i++) {
? ? ? ? ? ? echo "
? ? ? ? ? ? ? ? <tr>
? ? ? ? ? ? ? ? ? ? <td><input type='text' name='data[{$i}][name]'></td>
? ? ? ? ? ? ? ? ? ? <td><input type='text' name='data[{$i}][prix]'></td>
? ? ? ? ? ? ? ? ? ? <td><input type='text' name='data[{$i}][prixn]'></td>
? ? ? ? ? ? ? ? ? ? <td><input type='text' name='data[{$i}][quantite]'></td>
? ? ? ? ? ? ? ? ? ? <td>
? ? ? ? ? ? ? ? ? ? ? ? <select name='data[{$i}][unite]' id='unite_{$i}'>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <option>kg</option>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <option>G</option>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <option>L</option>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <option>Ml</option>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <option>Cl</option>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <option>Piece</option>
? ? ? ? ? ? ? ? ? ? ? ? </select>
? ? ? ? ? ? ? ? ? ? </td>
? ? ? ? ? ? ? ? </tr>
? ? ? ? ? ? ";
? ? ? ? }
? ? ? ? ?>
? ? </table>
? ? <button>Ajouter ingrédient</button>
</form>
</body>
</html>
以下是在 PHP 中將其作為多維數組進行訪問并使用準備好的語句插入到數據庫的示例。請記住,我在這里使用 PDO 而不是 mysqli,我建議您:
<?php
$data = $_POST['data'] ?? null;
if (!is_null($data)) {
? ? $pdo = new PDO("mysql:host=127.0.0.1;dbname=test;charset=utf8", "yourusername", "yourpassword");
? ? $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
? ? $stmt = $pdo->prepare("
? ? ? ? INSERT?
? ? ? ? INTO ingredient (name, prix, prixn, unite, quantite, date)?
? ? ? ? VALUES (:name, :prix, :prixn, :unite, :quantite, NOW())
? ? ? ? ");
? ? $stmt->bindParam('name', $name);
? ? $stmt->bindParam('prix', $prix);
? ? $stmt->bindParam('prixn', $prixn);
? ? $stmt->bindParam('quantite', $quantite);
? ? $stmt->bindParam('unite', $unite);
? ? foreach ($data as $item) {
? ? ? ??
? ? ? ? // Adds some data validation to make sure you won't save million empty rows,
? ? ? ? // also add custom validation for other fields (if any)
? ? ? ? ? ? ? ? ?
? ? ? ? $name = checkValue($item['name']);
? ? ? ? $prix = checkValue($item['prix']);
? ? ? ? $prixn = checkValue($item['prixn']);
? ? ? ? $quantite = floatval($item['quantite']);
? ? ? ? $unite = checkValue($item['unite']);
? ? ? ? if (!is_null($name) && !is_null($prix) && !is_null($prixn) && $quantite > 0) {
? ? ? ? ? ? $stmt->execute();
? ? ? ? }
? ? }
}
/**
?* check if the string value is not null and not empty
?*
?* @param $value
?*
?* @return string|null
?*/
function checkValue($value)
{
? ? return (is_null($value) || trim($value) == '') ? null : $value;
}
請注意,您的代碼很混亂,很可能我在表單中使用了錯誤的列名稱或字段名稱,只需修復它即可。一般來說,這是有效的。

TA貢獻1821條經驗 獲得超6個贊
您的代碼會受到 SQL 注入。最好使用參數化查詢。它們負責引用、修復可能包括 SQL 注入的數據等。重復執行相同的語句時它們的執行速度也更快。
注意:代碼未經測試,可能需要一些語法檢查和其他更正
<?php
// Create PDO connection
$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass);
// Create list of base column names
$colList = array(
'name',
'prix',
'prixn',
'uniteing'
);
// Create array to hold column values from $_POST
$val = Array(null,null,null,null);
// Prepare SQL statement with place holders, be sure to explicitly list the table column names. Substitute the actual column names for those below.
$stmt = $dbh->prepare("INSERT INTO ingredient (`namex`,`prixx`,`prixnx`,`uniteingx`) VALUES (:namex,:prixx,:prixnx,:uniteingx)");
// Bind each array value to a place holder
$stmt->bindParam(':namex',$val[1]);
$stmt->bindParam(':prixx',$val[2]);
$stmt->bindParam(':prinx',$val[3]);
$stmt->bindParam(':uniteingx',$val[4]);
// Step through the column name suffix values from the form
for($i=0;$i<=10;$i++) {
// Special case for the first (0) value (i.e. no suffix)
$suffix = $i > 0 ? $i : '';
// Load the 5 column values from the post variables into the $val array
foreach($colList as $colNum, $colName) {
$val[$colNum] = $_POST[$colName . $suffix];
}
// Execute the SQL statement above with the current values in $val
$stmt->execute();
}
?>

TA貢獻1827條經驗 獲得超8個贊
首先,制作您的 html 表單,使其適合目的并且不違反 html 文檔標準。
您應該在循環內生成輸入字段的行。
您應該
name
使用數組語法聲明每個字段的屬性,以便在分組的子數組中提交行數據——這將使后續過程變得更加容易。通過簡單地在字段名稱后面加上[]
,您可以避免不必要的 php 語法使您的文件變得混亂。id
單個文檔中不得有重復的屬性。您可以在字符串末尾附加一個計數器id
,但很可能您id
根本不需要這些聲明——我將省略它們。<option>
將的文本復制為其值的好處為零value
。只需省略該屬性聲明即可。<option>
使用測量單位白名單,這樣您就不需要一遍又一遍地寫出每個標簽。這將提高腳本的可維護性。為了改進用戶體驗,請使用字段屬性,例如:
title
、placeholder
、pattern
、minlength
、maxlength
、required
等,并可能type="number"
指導用戶如何形成有效條目。這些簡單的操作不僅有助于防止用戶感到沮喪,還可以使您的應用程序免于徒勞地訪問數據庫和/或僅存儲部分提交。
<table>
? ? <tr>
? ? ? ? <th>Nom Ingrédient</th>
? ? ? ? <th>Prix Ingrédient</th>
? ? ? ? <th>Quantite Ingrédient</th>
? ? ? ? <th>Unite</th>
? ? </tr>
? ? <?php
? ? $numberOfRows = 10;
? ? $units = ['kg', 'G', 'L', 'ml', 'Cl', 'Piece'];
? ? for ($i = 0; $i < $numberOfRows; ++$i) {
? ? ? ? ?>
? ? ? ? <tr>
? ? ? ? ? ? <td><input type="text" name="name[]"></td>
? ? ? ? ? ? <td><input type="text" name="price[]"></td>
? ? ? ? ? ? <td><input type="text" name="quantity[]"></td>
? ? ? ? ? ? <td>
? ? ? ? ? ? ? ? <select name="unit[]">
? ? ? ? ? ? ? ? ? ? <option><?php echo implode('</option><option>', $units); ?></option>
? ? ? ? ? ? ? ? </select>
? ? ? ? ? ? </td>
? ? ? ? </tr>
? ? ? ? <?php
? ? }
? ? ?>
</table>
至于數據庫表的設置,這里有一些提示:
避免模糊的列命名,例如
date
.?將列重命名為insert_date
或created_on
或類似的名稱,以便該值可以為您的腳本/項目的未來讀者提供更多信息。修改表的架構
ingredients
以將 DEFAULT 值設置insert_date
為 CURRENT_DATE。這樣做時,您永遠不需要將此列寫入 INSERT 查詢 - 當您不傳遞該列的值時,數據庫將自動使用當前日期。如果該表沒有 AUTOINCRMENTing
id
列,您應該添加一列并將其設為 PRIMARY KEY。這是一項非?;镜募夹g,可以改善將來與表的交互,并且可以消除當您發現有人name
向表中提交了重復項時可能出現的混亂。
至于處理您提交的數據,只需遵循幾個簡單的步驟:
迭代
$_POST
數組并隔離要插入數據庫的每一行數據。一旦隔離,您需要在執行查詢之前驗證并選擇性地清理每一行,以便您永遠不會在表中存儲“壞數據”。
您正在使用
mysqli
這很好——您不需要切換到 pdo 來編寫安全/穩定的代碼。4 您只需生成一次準備好的語句并將變量綁定到占位符一次。只有語句的(條件)執行需要在循環內。不過,我建議您從 mysqli 的過程語法切換到面向對象的語法。它更簡潔,我發現它更容易閱讀。
// create a mysqli connection object e.g. $mysqli = new mysqli(...$credentials);
$sql = "INSERT INTO ingredients (`id`, `name`, `price`, `quantity`, `unit`)
? ? ? ? VALUES (NULL, ?, ?, ?, ?)";?
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('sdds', $name, $price, $quantity, $unit);? // Assumes price and quantity are float values
$failures = [];
$affectedRows = 0;
$units = ['kg', 'G', 'L', 'ml', 'Cl', 'Piece'];
foreach ($_POST['name'] as $index => $name) {
? ? // adjust the validation/sanitization processes as you wish
? ? $name = trim($name);
? ? $price = trim($_POST['price'][$index]);
? ? $quantity = trim($_POST['quantity'][$index]);
? ? $unit = trim($_POST['unit'][$index]);
? ? $rowNo = $index + 1;
? ? if (!strlen($name) || !strlen($price) || !strlen($quantity) || !in_array($unit, $units)) {
? ? ? ? $failures[] = "Missing/Invalid value on row $rowNo";
? ? } elseif (!$stmt->execute());
? ? ? ? $failures[] = "A syntax error has occurred";? // check your error logs
? ? } else {
? ? ? ? ++$affectedRows;
? ? }
}
echo "Affected Rows: $affectedRows";
if ($failures) {
? ? echo "<ul><li>" , implode('</li><li>', $failures) , "</li></ul>";
}
一些總體建議:
避免混淆法語和英語。如果要使用法語變量名稱,請使用所有法語變量。也就是說,我讀過以英語為母語的人和英語作為第二語言開發人員的建議,他們指出您應該始終在代碼中使用所有英語 - 這是一場辯論,我現在不會對此進行權衡。
您會注意到,我在答案中從未調用過此函數。這是因為我們永遠不會將任何用戶輸入打印到屏幕上。證實?是的。消毒?當然。HTML 編碼?沒有;?不在這里,不現在。
如果這些成分行旨在與特定的
recipe
表行相關,那么您將需要建立外鍵關系。該recipes
表將需要一id
列,并且該ingredients
表將需要一列來recipe_id
存儲相應的配方id
。假設您的 html 表單已經知道正在引用哪個菜譜,您應該<input type="hidden" name="recipe" value="<?php echo $recipeId; ?>">
在標簽下的行中包含一個字段<form>
。然后,在保存數據時,您必須保存$_POST['recipe']
每個成分行的值。那么你就可以更好地使用“關系數據庫”。
- 3 回答
- 0 關注
- 227 瀏覽
添加回答
舉報