PHP 中的 Foreach 循环 - 全有或全无

Foreach Loops in PHP - All or nothing

在 foreach 循环中,假设我想执行以下操作

foreach($items as $item)
{

  // charge a user for purchasing an item - IS BEING DONE THROUGH AN API CALL WITH STRIPE
  // ie: \Stripe\Charge::create(...);

  // save some info to a database
  // using Laravel for this project so this is within a DB::transaction(...);


  // send a notification email to the buyer
  // Emails are being queued to avoid slowing down the request
  // ie: Mail::queue(...);
}

我希望出现全有或全无的情况。例如,如果在迭代过程中发生错误,那么 NONE 的商品将被收取费用,不会将任何信息保存到数据库中,买家也不会收到通知电子邮件。但是,如果 foreach 循环成功迭代了每个项目,则向用户收费,将信息保存到数据库,并发送通知电子邮件。我该怎么做?

您可能需要根据@Terminus 添加更多详细信息,并且 if/why 您对每件商品单独收费。但是根据您的需要,您可以在循环期间构建数据库查询,而无需执行它直到循环结束。然后,您将不得不回滚所有费用(根据您的实施),然后根据需要发送一封或多封电子邮件。

您可以计算数组中的项目数并进行一些更改以使其工作:

$result = count($items);
$c = 0;
foreach($items as $item)
{
// charge a user for purchasing an item -- instead add it to a buffer as total 
//amount.
// save some info to a database ---instead prepare your db statements here
// send a notification email to the buyer.--this could be sent out for all the 
//items in the order together outside the loop instead of inside the loop.
$c = $c + 1;
}
if($c == $cc)
{
//execute your prepared statements here..and also the other email and charging stuff.
}
else{
 //Error code. 
 }

你有选择。

我能想到的最简单的方法是遍历数组两次;第一次检查条件,第二次仅在第一个 运行 没有发现问题时检查。

$isGoodToGo = true;
foreach($items as $item) {
  if (conditon met) {
    $isGoodToGo = false;
    break; // stop iterating over the array cause condition is met
  }
}

if ($isGoodToGo) {
  foreach($items as $item) {
    // charge a user for purchasing an item
    // save some info to a database
    // send a notification email to the buyer
  }
}

我建议使用交易并在最后通知买家。

Mysqli 示例:

$dbConn->begin_transaction();

try{

    foreach($ítems as $item){
        //Whatever you are going to do
    }

    if($dbConn->commit()){

    //Notify buyer about all the transactions, the user doesn't receives the notification unless the commit was succesful

   }

catch(Exception ex){
    $dbConn->rollback();
}

此外,您可以验证 mysqli 函数的 return 值,我只想关注事务使用。