WHILE循环中的FOREACH循环多次运行 - PHP

时间:2015-07-27 18:38:01

标签: php loops mysqli foreach

我正在尝试通过php运行mysqli查询,该查询将根据所选内容更新项目的数量。因此,如果用户选择两个数量的项目,那么该数量应该减少两个。我可以成功地执行此操作而无需使用此代码:

$postparts = $_POST['part_name']; <-- This is an array of the items chosen
$postqty = $_POST['qty']; <-- This is an array of the qty of each item chosen

$combine = array_combine($postparts, $postqty); <-- I combine the arrays to match the qty to the item that was chosen.  

foreach ($combine as $part=>$qty)
    {
        $update = <<<SQL
UPDATE `Houston` SET `qty` = (`qty`-?) WHERE `partnumber` = ?;
SQL;
        $result = $mysqli->prepare($update);
        $result->bind_param("is", $qty, $part);
        $result->execute();
    }

上面的代码会从所选项目中减去相应的数量 - 这里没有问题。但是,我需要实施一个额外的检查,这样如果两个人同时检查同一个项目,第一个会得到一个成功的结果,但如果该项目的数量因为第一个结账流程那么为0 ,第二个人会失败。我试着这样做:

$postparts = $_POST['part_name'];
$postqty = $_POST['qty'];

$partarray = array();
foreach ($postparts as $part => $id)
{
    $finalpart = ($postparts[$part]);
    $stuff = explode(',', $finalpart);
    $partarray = array_merge($partarray, $stuff);
}

$combine = array_combine($postparts, $postqty);
$in = implode(',', array_fill(0, count($partarray), '?'));
$check = <<<SQL
SELECT * FROM `Houston` WHERE `partnumber` in ($in);
SQL;

$statcheck = $mysqli->prepare($check);
$statcheck->bind_param(str_repeat('s', count($partarray)), ...$partarray);
$statcheck->execute();
$statcheck->store_result();
$statcheck->bind_result($id, $partcat, $partnumber, $partqty);
while ($statcheck->fetch())
{
    if ($partqty > 0)
    {
        foreach ($combine as $part=>$qty)
        {
            $update = <<<SQL 
UPDATE `Houston` SET `qty` = (`qty`-?) WHERE `partnumber` = ?;
SQL;
            $result = $mysqli->prepare($update);
            $result->bind_param("is", $qty, $part);
            $result->execute();
        }
   }
   if ($partqty == 0)
   {
        header("location:error.php");
   }
}

所以这&#34;几乎&#34;工作 - 除了foreach循环多次运行。假如用户检出两个项目 - 那么foreach循环运行两次 - 因此订购的数量最终会使每个项目加倍(如果有3个项目,则数量增加三倍等)。我怀疑这种行为的原因是因为我在while循环中运行foreach循环,但我不知道如何解决这个问题以使其正常工作。谁知道怎么做?

2 个答案:

答案 0 :(得分:0)

您完全不了解准备好的语句。顾名思义,你只需准备一次。

此外,选择数据只是为了更新它没有意义。无论您需要检查什么,都必须通过SQL查询进行检查。

$combine = array_combine($postparts, $postqty);
$sql = "UPDATE Houston SET qty = qty-?) WHERE partnumber=? AND qty > 0";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("is", $qty, $part);
foreach ($combine as $part=>$qty)
{
    $stmt->execute();
}
  

我需要实施一个额外的检查,以便如果两个人同时检查同一个项目,第一个会得到一个成功的结果,但如果该项目的数量因为第一次结账而为0过程中,第二个人会失败。

你需要表锁定。如果你确实需要这样的检查。

要查看更新是否成功,请使用PDOStatement::rowCount()

答案 1 :(得分:-1)

我能够找到一个有效的解决方案,但不确定它是否是最优雅的解决方案。如果有人有更好的主意,请告诉我。

$postparts = $_POST['part_name'];
$postqty = $_POST['qty'];
$combine = array_combine($postparts, $postqty);

$update = <<<SQL
UPDATE `Houston` SET `qty` = (`qty`-?) WHERE `partnumber` = ?;
SQL;
$result = $mysqli->prepare($update);
$result->bind_param("is", $qty, $part);

$check = <<<SQL
SELECT * FROM `Houston` WHERE `partnumber` = ?;
SQL;
$checkpart = $mysqli->prepare($check);
$checkpart->bind_param('s', $part);

foreach ($combine as $part=>$qty)
{
    $checkpart->execute();
    $checkpart->store_result();
    $checkpart->bind_result($id, $partcat, $partnumber, $partqty);

    if ($checkpart->fetch())
    {
        if ($partqty > 0)
        {
            $result->execute();
        }
        elseif ($partqty == 0)
        {
            header("location:error.php");
        }
    }
}