【问题标题】:PHP Form $_POST foreach stops after first iterationPHP Form $_POST foreach 在第一次迭代后停止
【发布时间】:2019-11-05 08:54:44
【问题描述】:

我有以下 PHP 代码,它从另一个文件中提取已发布的表单数据,执行 SELECT 查询以从各种表(SalesDB、CustDB 和 ProdDB)中查找所有相关数据,然后执行 INSERT INTO 查询以添加行到“SalesDB”表中。表单具有动态添加的行,这为每个新添加的行提供了唯一的 ID,例如:

...<input type="text" id="prodName_1" name="prodName[]" value="">
...<input type="text" id="prodName_2" name="prodName[]" value="">
.  
.  
...<input type="text" id="prodName_Z" name="prodName[]" value="">

但是,当 PHP 脚本运行时,例如3 行产品线,它只执行第一次迭代的 $queryinsert 查询并插入表单的第一个产品线。为什么它不会循环遍历数组?请参阅下面的 php 脚本:

<?php

$db = new SQLite3('../xxx.db');
if(!$db){
  echo $db->lastErrorMsg();
  exit;
}

if (empty($_POST['custID'])) {
  $errorMSG = array("No customer selected");
  echo json_encode($errorMSG, JSON_PRETTY_PRINT);
  exit;
} else {

  $custID = $_POST['custID'];

  $queryInsert = $db->prepare("INSERT INTO 'SalesDB'
  (SalesID,CustID,ProdID,ProdQty,ProdPrice,ProdCurr,ProdVAT,SalesPrice,SalesVAT,SalesSum)
  VALUES (?,?,?,?,?,?,?,?,?,?)");
  $queryInsert->bindParam(1,$salesID);
  $queryInsert->bindParam(2,$custID);
  $queryInsert->bindParam(3,$prodID);
  $queryInsert->bindParam(4,$prodQty);
  $queryInsert->bindParam(5,$prodPrice);
  $queryInsert->bindParam(6,$prodCurr);
  $queryInsert->bindParam(7,$prodVAT);
  $queryInsert->bindParam(8,$salesPrice);
  $queryInsert->bindParam(9,$salesVAT);
  $queryInsert->bindParam(10,$salesSum);

  $querySalesID = "SELECT MAX(SalesID) AS max_SalesID FROM 'SalesDB'";
  $resultSalesID = $db->query($querySalesID);

  while ($row = $resultSalesID->fetchArray()) {
    $salesID = $row['max_SalesID'] + 1;
  }

  foreach($_POST['prodName'] as $prodName => $value) {
    if (!$value) {
      $errorMSG = array("Empty product fields");
      echo json_encode($errorMSG, JSON_PRETTY_PRINT);
      exit;
    } elseif ($value == "Product not found") {
      $errorMSG = array("Invalid products in order form");
      echo json_encode($errorMSG, JSON_PRETTY_PRINT);
      exit;
    }

    $queryProd = "SELECT * FROM `ProdDB` WHERE ProdName LIKE '%$value%'";
    $resultProd = $db->query($queryProd);

    while ($row = $resultProd->fetchArray()) {
      $prodID = $row['ProdID'];
      $prodPrice = $row['ProdPrice'];
      $prodQty = $row['ProdQty'];
      $prodVAT = $row['ProdVAT'];
      $prodCurr = $row['ProdCurr'];
      $salesPrice = $prodQty * $prodPrice;
      $salesVAT = number_format($prodQty * $prodPrice * $prodVAT,2);
      $salesSum = $salesPrice + $salesVAT;
    }
    $result = $queryInsert->execute();
  }
}
?>

还请注意,我知道我(很可能)在安全实践或编程标准方面犯了很多错误,但整个事情 (PHPDesktop > https://github.com/cztomczak/phpdesktop) 将被打包到一个 EXE 文件中它将仅在本地运行(不需要在线连接,因为 SQLite3 DB 与 EXE 打包在一起),而且我仍在研究如何首先对其进行编程,因此高效和整洁的编码在我的列表中并不高然而;-)

【问题讨论】:

  • @04FS 只有在 $_POST 为空或值为“未找到产品”时才会触发退出注释。如果两者都不适用,它将跳过此代码并继续执行 $queryProd 语句,该语句没有退出语句。
  • “为什么它不循环遍历数组?” - 你真的验证过它没有这样做吗?您的查询没有错误控制 - 所以谁说$queryInsert-&gt;execute() 不只是默默地失败了?
  • @04FS 如果我要插入3行数据,执行脚本后我只能看到第一行添加到数据库中,而第二行和第三行不在数据库中。
  • 这正是我所指的完全 - 您只查看结果,而不是检查脚本中实际发生的情况!去正确地调试它。首先检查您的数据库查询是否真的成功 - 在您的脚本中
  • @RoyMonden 嗨,如果我的回答对您有帮助,请将其标记为已接受(带有绿色 V)

标签: php phpdesktop


【解决方案1】:

脚本中存在一些问题:

1) 不要在foreach 中执行exit,而是执行continue 以跳过单个实际迭代。

official documentation

continue 在循环结构中用于跳过其余的 当前循环迭代并在条件下继续执行 评估,然后开始下一次迭代。

试试这个代码:

  foreach($_POST['prodName'] as $prodName => $value) {
    if (!$value) {
      $errorMSG = array("Empty product fields");
      echo json_encode($errorMSG, JSON_PRETTY_PRINT);
      continue;
    } elseif ($value == "Product not found") {
      $errorMSG = array("Invalid products in order form");
      echo json_encode($errorMSG, JSON_PRETTY_PRINT);
      continue;
    }

    $queryProd = "SELECT * FROM `ProdDB` WHERE ProdName LIKE '%$value%'";
    $resultProd = $db->query($queryProd);

    while ($row = $resultProd->fetchArray()) {
      $prodID = $row['ProdID'];
      $prodPrice = $row['ProdPrice'];
      $prodQty = $row['ProdQty'];
      $prodVAT = $row['ProdVAT'];
      $prodCurr = $row['ProdCurr'];
      $salesPrice = $prodQty * $prodPrice;
      $salesVAT = number_format($prodQty * $prodPrice * $prodVAT,2);
      $salesSum = $salesPrice + $salesVAT;
    }
    $result = $queryInsert->execute();
  }

2)您的查询正在使用用户输入而不检查其内容,因此您的脚本可能会打开到SQLInjection

$queryProd = "SELECT * FROM `ProdDB` WHERE ProdName LIKE '%$value%'";

3) 如果查询没有返回任何内容,则脚本不会进入while 循环,因此foreach 似乎只进行了一次迭代,而是在不进行所有迭代的情况下进行输入while,因为该查询的结果为空。

我建议您通过使用var_dump 打印出变量内容来调试您的所有代码片段,例如:

$a = array(1, 2, array("a", "b", "c"));
var_dump($a);

【讨论】:

  • 我试了一下,但没有什么不同。此外,我不认为“退出”语句会成为问题,因为只有在 $_POST 为空或值为“未找到产品”时才会触发该语句。如果两者都不适用,它将跳过此代码并继续执行 $queryProd 语句。
  • 我有,但遗憾的是我是 JS 和 PHP 的新手,因此我无法让 var_dump 工作。问题是我在一个名为 PHPDesktop 的系统中工作(github.com/cztomczak/phpdesktop,这就是为什么我不担心 SQL 注入,因为这将被打包到离线 EXE 中),因此没有运行本地服务器。此外,我没有运行 IDE,而只有一个代码编辑器(Atom io),因此我必须尝试让它通过反复试验来工作。
  • @RoyMonden 在你的问题中解释我编辑它。您将提高问题质量,并且可能会从熟悉您的工具的人那里获得解决方案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 2020-12-15
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多