为了账号安全,请及时绑定邮箱和手机立即绑定

如何将 html 表单中的多行提交到数据库表中?

如何将 html 表单中的多行提交到数据库表中?

PHP
慕田峪7331174 2023-10-15 15:17:28
我想仅用一个函数插入所有值,并且不想多次重写相同的代码,但我遇到的问题是该函数仅插入第一个值(我检查了输入名称并且设置正确)。$name = htmlspecialchars($_POST["name"]);  $prix = htmlspecialchars($_POST["prixing"]); $prixn = htmlspecialchars($_POST["quantite"]);  $uniteing = $_POST['unite']; $date = date('Y-m-d');<?php$servername = "localhost"; $username = "root"; $password = "test"; $dbname = "test";// Create connection $conn = mysqli_connect($servername, $username, $password, $dbname);// Check connection if (!$conn) {   die("Connection failed: " . mysqli_connect_error());    }  //   variable $date = date('Y-m-d');$name = htmlspecialchars($_POST["name"]);      $name1 = htmlspecialchars($_POST["name1"]); $prix = htmlspecialchars($_POST["prixing"]);   $prix1 = htmlspecialchars($_POST["prixing1"]); $prixn = htmlspecialchars($_POST["quantite"]); $prixn1 = htmlspecialchars($_POST["quantite1"]); $uniteing = $_POST['unite'];    $uniteing1 = $_POST['unite1'];$name2 = htmlspecialchars($_POST["name2"]);          $name3 = htmlspecialchars($_POST["name3"]); $prix2 = htmlspecialchars($_POST["prixing2"]);       $prix3 = htmlspecialchars($_POST["prixing3"]); $prixn2 = htmlspecialchars($_POST["quantite2"]);     $prixn3 = htmlspecialchars($_POST["quantite3"]); $uniteing2= $_POST['unite2'];   $uniteing3 = $_POST['unite3'];$name4 = htmlspecialchars($_POST["name4"]);          $name5 = htmlspecialchars($_POST["name5"]); $prix4 = htmlspecialchars($_POST["prixing4"]);       $prix5 = htmlspecialchars($_POST["prixing5"]); $prixn4 = htmlspecialchars($_POST["quantite4"]);     $prixn5 = htmlspecialchars($_POST["quantite5"]); $uniteing4 = $_POST['unite4'];  $uniteing5 = $_POST['unite5'];$name6 = htmlspecialchars($_POST["name6"]);          $name7 = htmlspecialchars($_POST["name7"]); $prix6 = htmlspecialchars($_POST["prixing6"]);       $prix7 = htmlspecialchars($_POST["prixing7"]); $prixn6 = htmlspecialchars($_POST["quantite6"]);     $prixn7 = htmlspecialchars($_POST["quantite7"]); $uniteing6 = $_POST['unite6'];  $uniteing7 = $_POST['unite7'];
查看完整描述

3 回答

?
波斯汪

TA贡献1811条经验 获得超4个赞

您不应该将表单字段作为列表重复name0name1..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;

}

请注意,您的代码很混乱,很可能我在表单中使用了错误的列名称或字段名称,只需修复它即可。一般来说,这是有效的。


查看完整回答
反对 回复 2023-10-15
?
达令说

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();

}



?>


查看完整回答
反对 回复 2023-10-15
?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

首先,制作您的 html 表单,使其适合目的并且不违反 html 文档标准。

  • 您应该在循环内生成输入字段的行。

  • 您应该name使用数组语法声明每个字段的属性,以便在分组的子数组中提交行数据——这将使后续过程变得更加容易。通过简单地在字段名称后面加上[],您可以避免不必要的 php 语法使您的文件变得混乱。

  • id单个文档中不得有重复的属性。您可以在字符串末尾附加一个计数器id,但很可能您id根本不需要这些声明——我将省略它们。

  • <option>将的文本复制为其值的好处为零value。只需省略该属性声明即可。

  • <option>使用测量单位白名单,这样您就不需要一遍又一遍地写出每个标签。这将提高脚本的可维护性。

  • 为了改进用户体验,请使用字段属性,例如:titleplaceholderpatternminlengthmaxlengthrequired等,并可能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_datecreated_on或类似的名称,以便该值可以为您的脚本/项目的未来读者提供更多信息。

  • 修改表的架构ingredients以将 DEFAULT 值设置insert_date为 CURRENT_DATE。这样做时,您永远不需要将此列写入 INSERT 查询 - 当您不传递该列的值时,数据库将自动使用当前日期。

  • 如果该表没有 AUTOINCRMENTingid列,您应该添加一列并将其设为 PRIMARY KEY。这是一项非常基本的技术,可以改善将来与表的交互,并且可以消除当您发现有人name向表中提交了重复项时可能出现的混乱。


至于处理您提交的数据,只需遵循几个简单的步骤:

  1. 迭代$_POST数组并隔离要插入数据库的每一行数据。

  2. 一旦隔离,您需要在执行查询之前验证并选择性地清理每一行,以便您永远不会在表中存储“坏数据”。

  3. 您正在使用mysqli这很好——您不需要切换到 pdo 来编写安全/稳定的代码。4 您只需生成一次准备好的语句并将变量绑定到占位符一次。只有语句的(条件)执行需要在循环内。

  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>";

}

一些总体建议:

  1. 避免混淆法语和英语。如果要使用法语变量名称,请使用所有法语变量。也就是说,我读过以英语为母语的人和英语作为第二语言开发人员的建议,他们指出您应该始终在代码中使用所有英语 - 这是一场辩论,我现在不会对此进行权衡。

  2. 您会注意到,我在答案中从未调用过此函数。这是因为我们永远不会将任何用户输入打印到屏幕上。证实?是的。消毒?当然。HTML 编码?没有; 不在这里,不现在。

  3. 如果这些成分行旨在与特定的recipe表行相关,那么您将需要建立外键关系。该recipes表将需要一id列,并且该ingredients表将需要一列来recipe_id存储相应的配方id。假设您的 html 表单已经知道正在引用哪个菜谱,您应该<input type="hidden" name="recipe" value="<?php echo $recipeId; ?>">在标签下的行中包含一个字段<form>。然后,在保存数据时,您必须保存$_POST['recipe']每个成分行的值。那么你就可以更好地使用“关系数据库”。


查看完整回答
反对 回复 2023-10-15
  • 3 回答
  • 0 关注
  • 165 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信