3 回答

TA貢獻(xiàn)1811條經(jīng)驗 獲得超4個贊
您不應(yīng)該將表單字段作為列表重復(fù)name0
,name1
..name99
相反,您需要將它們作為數(shù)組發(fā)送,例如:data[0][name]
..data[99][name]
另外,最好使用 PHP 生成 HTML,以免違反DRY 規(guī)則,您會意識到將來何時需要使用重復(fù)字段編輯表單:
<!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 中將其作為多維數(shù)組進行訪問并使用準(zhǔn)備好的語句插入到數(shù)據(jù)庫的示例。請記住,我在這里使用 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;
}
請注意,您的代碼很混亂,很可能我在表單中使用了錯誤的列名稱或字段名稱,只需修復(fù)它即可。一般來說,這是有效的。

TA貢獻(xiàn)1821條經(jīng)驗 獲得超6個贊
您的代碼會受到 SQL 注入。最好使用參數(shù)化查詢。它們負(fù)責(zé)引用、修復(fù)可能包括 SQL 注入的數(shù)據(jù)等。重復(fù)執(zhí)行相同的語句時它們的執(zhí)行速度也更快。
注意:代碼未經(jīng)測試,可能需要一些語法檢查和其他更正
<?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貢獻(xiàn)1827條經(jīng)驗 獲得超8個贊
首先,制作您的 html 表單,使其適合目的并且不違反 html 文檔標(biāo)準(zhǔn)。
您應(yīng)該在循環(huán)內(nèi)生成輸入字段的行。
您應(yīng)該
name
使用數(shù)組語法聲明每個字段的屬性,以便在分組的子數(shù)組中提交行數(shù)據(jù)——這將使后續(xù)過程變得更加容易。通過簡單地在字段名稱后面加上[]
,您可以避免不必要的 php 語法使您的文件變得混亂。id
單個文檔中不得有重復(fù)的屬性。您可以在字符串末尾附加一個計數(shù)器id
,但很可能您id
根本不需要這些聲明——我將省略它們。<option>
將的文本復(fù)制為其值的好處為零value
。只需省略該屬性聲明即可。<option>
使用測量單位白名單,這樣您就不需要一遍又一遍地寫出每個標(biāo)簽。這將提高腳本的可維護性。為了改進用戶體驗,請使用字段屬性,例如:
title
、placeholder
、pattern
、minlength
、maxlength
、required
等,并可能type="number"
指導(dǎo)用戶如何形成有效條目。這些簡單的操作不僅有助于防止用戶感到沮喪,還可以使您的應(yīng)用程序免于徒勞地訪問數(shù)據(jù)庫和/或僅存儲部分提交。
<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>
至于數(shù)據(jù)庫表的設(shè)置,這里有一些提示:
避免模糊的列命名,例如
date
.?將列重命名為insert_date
或created_on
或類似的名稱,以便該值可以為您的腳本/項目的未來讀者提供更多信息。修改表的架構(gòu)
ingredients
以將 DEFAULT 值設(shè)置insert_date
為 CURRENT_DATE。這樣做時,您永遠(yuǎn)不需要將此列寫入 INSERT 查詢 - 當(dāng)您不傳遞該列的值時,數(shù)據(jù)庫將自動使用當(dāng)前日期。如果該表沒有 AUTOINCRMENTing
id
列,您應(yīng)該添加一列并將其設(shè)為 PRIMARY KEY。這是一項非?;镜募夹g(shù),可以改善將來與表的交互,并且可以消除當(dāng)您發(fā)現(xiàn)有人name
向表中提交了重復(fù)項時可能出現(xiàn)的混亂。
至于處理您提交的數(shù)據(jù),只需遵循幾個簡單的步驟:
迭代
$_POST
數(shù)組并隔離要插入數(shù)據(jù)庫的每一行數(shù)據(jù)。一旦隔離,您需要在執(zhí)行查詢之前驗證并選擇性地清理每一行,以便您永遠(yuǎn)不會在表中存儲“壞數(shù)據(jù)”。
您正在使用
mysqli
這很好——您不需要切換到 pdo 來編寫安全/穩(wěn)定的代碼。4 您只需生成一次準(zhǔn)備好的語句并將變量綁定到占位符一次。只有語句的(條件)執(zhí)行需要在循環(huán)內(nèi)。不過,我建議您從 mysqli 的過程語法切換到面向?qū)ο蟮恼Z法。它更簡潔,我發(fā)現(xiàn)它更容易閱讀。
// 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>";
}
一些總體建議:
避免混淆法語和英語。如果要使用法語變量名稱,請使用所有法語變量。也就是說,我讀過以英語為母語的人和英語作為第二語言開發(fā)人員的建議,他們指出您應(yīng)該始終在代碼中使用所有英語 - 這是一場辯論,我現(xiàn)在不會對此進行權(quán)衡。
您會注意到,我在答案中從未調(diào)用過此函數(shù)。這是因為我們永遠(yuǎn)不會將任何用戶輸入打印到屏幕上。證實?是的。消毒?當(dāng)然。HTML 編碼?沒有;?不在這里,不現(xiàn)在。
如果這些成分行旨在與特定的
recipe
表行相關(guān),那么您將需要建立外鍵關(guān)系。該recipes
表將需要一id
列,并且該ingredients
表將需要一列來recipe_id
存儲相應(yīng)的配方id
。假設(shè)您的 html 表單已經(jīng)知道正在引用哪個菜譜,您應(yīng)該<input type="hidden" name="recipe" value="<?php echo $recipeId; ?>">
在標(biāo)簽下的行中包含一個字段<form>
。然后,在保存數(shù)據(jù)時,您必須保存$_POST['recipe']
每個成分行的值。那么你就可以更好地使用“關(guān)系數(shù)據(jù)庫”。
- 3 回答
- 0 關(guān)注
- 224 瀏覽
添加回答
舉報