Reputation: 487
In a foreach loop, say I wanted to do the following
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(...);
}
I would like an all or nothing situation to occur. For example, if an error occurs during the iteration, then NONE of the items are charged, no information is saved to the database, and the buyer does not get a notification email. However, if the foreach loop successfully iterates over each item, then charge the user, save info to database, and send notification email. How do I do this?
Upvotes: 0
Views: 1454
Reputation: 3115
I would recommend using Transactions and notifying the buyer at the end.
Mysqli Example:
$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();
}
Additionally you could verify the return values of the mysqli functions, I Just wanted to focus on the transaction use.
Upvotes: 1
Reputation: 11
You can count the no of items in the array and make some changes to make it work:
$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.
}
Upvotes: 0
Reputation: 9402
You might need to add some more detail as per @Terminus as well as if/why you are charging each item separately. But depending on your needs, you could build the db query during the loop without executing it until the end of the loop. You would then have to roll back any charges (as per your implementation) and then send one or more emails as appropriate.
Upvotes: 0
Reputation:
You have options.
Easiest way i can think of is loop over the array twice; the first time checking the condition and the 2nd only if the first run through found no problems.
$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
}
}
Upvotes: 0