【问题标题】:Submitting form values to database, php将表单值提交到数据库,php
【发布时间】:2017-05-04 14:57:42
【问题描述】:

我目前有一个根据上传的 CSV 构建的表单。当用户上传 CSV 并点击“预览”按钮时,它会定向到一个窗口,该窗口在可编辑的表格中显示整个 CSV。 CSV 是 5 条记录和 229 个字段。输入名称是根据行数和列数构建的,因此对于此 CSV,它应该从 row1col1 开始并转到 row5col229。

我发现名称按预期工作,但我仍然遇到问题。一些 CSV 文件将有 4 行,有些可能有 8 或 9 行。我需要找到一种方法来获取表单输入并将其全部提交到 229 字段临时表中。

有没有一种方法可以为一行创建一个数组和语句,并为实际存在的多行循环它?

这是我当前的代码:

if(isset($_POST['preview']))
{
ini_set('auto_detect_line_endings', true);


$file = $_FILES["file"]["tmp_name"];
$handle = fopen($file, "r");
$maxPreviewRows = PHP_INT_MAX;  // this will be ~2 billion on 32-bit system, or ~9 quintillion on 64-bit system
$hasHeaderRow = true;
    echo '<form method="post">';
    echo '<table>';

    if ($hasHeaderRow) {
        $headerRow = fgetcsv($handle);
        echo '<thead><tr>';
        foreach($headerRow as $value) {
            echo "<th>$value</th>";
        }
        echo '</tr></thead>';
    }

    echo '<tbody>';

    $rowCount = 0;
    while ($row = fgetcsv($handle)) {
        $colCount = 0;
        echo '<tr>';
        foreach($row as $value) {
        echo "<td><input name='row".$rowCount."col".$colCount."' type='text' value='$value' /></td>";

            $colCount++;
        }
        echo '</tr>';

        if (++$rowCount > $maxPreviewRows) {
            break;
        }
    }
    echo '</tbody></table>';
    echo '<input type=\'submit\' value=\'Submit\' >';
    var_dump($_POST);
    echo '</form>';
}
?> 

我觉得我走在正确的轨道上,但我不知道如何构建元素数组或语句,以便它成为一个模板,可以这么说,并为所有行循环它。

【问题讨论】:

  • 我回滚了你的编辑并将你的编辑放在你的答案而不是你的问题上!

标签: php html mysql forms csv


【解决方案1】:

回复the Answer by Tom上的cmets:

您可以将表单中的值设置为数组 $_POST['rows']['columns'] 广告然后简单地 count($_POST['rows']);对值进行计数,然后对行中的每个值进行 foreach。

--马丁

所以我不需要遍历并声明 229 个元素?只需创建数组并计数,然后使用 foreach 循环?在这种情况下,我将如何在 SQL 中创建一条语句以插入到数据库中?

-- 汤姆

您的表单将是一个 POST 值数组,例如

foreach($row as $value) {
        echo "<td><input name='row[".$rowCount."][".$colCount."]' type='text' value='$value' /></td>";

            $colCount++;
        }  

这将产生一个数组 POST 值,例如:

$_POST['row'][1][1] = $value;
$_POST['row'][1][2] = $value;
$_POST['row'][1][3] = $value;
...
$_POST['row'][1][229] = ...;
$_POST['row'][2][1] = ... ;
...
$_POST['row'][2][229] = ...;
...
$_POST['row'][5][229] = ...;

然后您可以在此数组上运行foreach 循环,然后为数组的每个键提取保存的数据的值:

$sql = $inserts = $binds = [];
foreach ($_POST['row'] as $rowValue){
    if(is_array($rowValue) && count($rowValue) > 0 ){
        foreach($rowValue as $rowData){
           /***
            * Stupidly, I had missed that row contains arrays 
            * rather than values, so you need a foreach, inside the 
            * foreach as so:
            ***/
            foreach ($rowData as $columnKey  => $columnValue){
                //$columnValue will now equal $value
                //$columnKey will be the column number (1...229)
                /***
                 * This is the area you can construct your SQL query values.
                 * db_connection is assumed to be setup.
                 ***/
                 $sql[] = "`column_name_".$columnKey."`"
                 $binder = "value".$columnKey;
                 $inserts[] = ":".$binder;
                 $binds[$binder] = $columnValue;
                 unset($binder);
            }
           unset($columnKey,$columnValue);             
       }
       unset($rowData);
       /***
        * This is the area the SQL query is set on a per row basis
        ***/
       $sqlFull = "INSERT INTO <table> (".implode(",",$sql).") VALUES(".implode(",",$inserts).")";
       $db_connection->prepare($sqlFull); 
       /***
        * EDIT: bind param MUST come after the prepare call
        ***/
       foreach($binds as $bindKey=>$bindRow){
            $db_connection->bind_param(":".$bindKey, $bindRow);
       }
       unset($bindKey,$bindRow);      
       $sql = $inserts = $binds = []; //reset arrays for next row iteration. 
       /***
        * db_connection then executes the statement constructed above
        ***/
        $db_connection->execute();
     } //close if.
}
unset($rowValue);

请注意这只是一个快速而肮脏的例子,我没有时间检查我的语法是否准确,但它更多的是让你对查询结构有一个粗略的了解

您可以使用count() 计算$_POST 数组中的行数和列数。

【讨论】:

  • 恐怕这需要一些编辑,因为你不能在-&gt;bindparam 之前设置-&gt;prepare
  • @TomN。我已经更新了我的答案,所以绑定参数现在应该可以正常工作了。我必须强烈鼓励您查看准备好的声明并充分利用PHP error logging。它将比空白屏幕更快地找到问题!祝你好运!
  • @TomN。我不喜欢用isset,我觉得这个功能太模糊了。
  • 我发现了这个问题,我的答案中的foreach 循环没有考虑到row 包含 数组(列)。我会编辑它....
  • @TomN。我建议的方法是将 print_r() 放入每个变量的代码中(每个变量都有一个描述器,例如 print "binder: ".print_r($binder,true)."&lt;br&gt;"; )并像这样处理它,以查看确切的数据放置在哪里,然后使用它来调整代码,以便数据是 SQL 使用的正确形状。从这里你也应该能够更实际地看到实际发生了什么以及在哪里。祝你好运。
【解决方案2】:

我实际上已经弄清楚了,并且名称按预期工作。但是,我有一个问题。有些 CSV 文件会有 5 行,有些会有更多,所以我不能通过输入名称来创建静态方式来执行此操作。有没有一种方法可以创建一个数组和语句,并为存在多少行循环它?


编辑 当前用于解决 cmets 中向 Martins 回答的问题的源代码。

<?
$connect = mysqli_connect($server, $user, $pw, $db);

if ($connect->connect_error) {
die("Connection failed: " . $conn->connect_error);
}else{
echo'success!';
}

 var_dump($_POST);


     $sql = $inserts = $binds = [];
           foreach ($_POST['row'] as $rowValue){
         if(is_array($rowValue) && count($rowValue) > 0 ){
                foreach($rowValue as $columnKey  => $columnValue){
       //$columnValue will now equal $value
       //$columnKey will be the column number (1...229)
       /***
        * This is the area you can construct your SQL query values.
        * db_connection is assumed to be setup.
        ***/
        $sql[] = "`column_name_".$columnKey."`";
        $binder = "value".$columnKey;
        $inserts[] = ":".$binder;  
        $binds[$binder] = $columnValue;
        unset($binder);
    }
   unset($columnKey,$columnValue);
   /***
    * This is the area the SQL query is set on a per row basis
    ***/
   $sqlFull = "INSERT INTO staging (".implode(",",$sql).") VALUES(".implode(",",$inserts).")";
   $connect->prepare($sqlFull); 
   /***
    * EDIT: bind param MUST come after the prepare call
    ***/
   foreach($binds as $bindKey=>$bindRow){
        $connect->bind_param(":".$bindKey, $bindRow);
   }

   unset($bindKey,$bindRow); 
   var_dump($binds);   
   $sql = $inserts = $binds = []; //reset arrays for next row iteration. 
   /***
    * db_connection is then given the SQL. 
    ***/
    $connect->execute();

  echo "<p>\$sqlFull:<pre>".print_r($sqlFull,true)."</pre></p>\n";

  if(mysqli_multi_query($connect, $sqlFull)) 
  {
    echo'File submitted'; 
  } else { 
    echo "Error: " . mysqli_error($connect); 
  }
 } //close if.


}

unset($rowValue);



?>

【讨论】:

  • 您可以将表单中的值设置为数组 $_POST['rows']['columns'] 广告,然后只需 count($_POST['rows']); 对值进行计数,然后将 foreach 设置为行中的每个值。
  • 所以我不需要通过并声明 229 个元素?只需创建数组并计数,然后使用 foreach 循环?在这种情况下,我将如何在 SQL 中创建一条语句以插入数据库?
  • 这是一个很大的问题;您可以使用 foreach 循环构造 SQL 插入的参数,然后在循环之后运行插入。 SO上会有很多参考资料
  • 好的,我想我明白了。我会研究一下,谢谢
猜你喜欢
  • 1970-01-01
  • 2018-03-11
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-12
  • 1970-01-01
相关资源
最近更新 更多