简体   繁体   中英

How do I set condition in foreach loop with array in php

I have two array one is for email list and the other one is smtp array I want to apply certain condition in foreach loop and sending email but with the condition below is my code.

I have tried it with the code I pasted here but Its not working as expected as I want to apply limit on smtp to send only specified in smtp array limit array.

$emails = array(            
    "test1@gmail.com",
    "test2@gmail.com",
    "test3@gmail.com",
    "test4@gmail.com",
    "test5@gmail.com",
    "test6@gmail.com",
    "test7@gmail.com",
    "test8@gmail.com",
    "test9@gmail.com",
    "test10@gmail.com",
    "tes11@gmail.com",
    "test12@gmail.com",
    "test13@gmail.com",
    "test14@gmail.com",
    "test15@gmail.com",
    "test16@gmail.com",
    "test17@gmail.com",
    "test18@gmail.com",
    "test19@gmail.com",
    "test20@gmail.com",
);

/*I have set smtp array with Its Daily Limit Count*/
$smtp=array(
    array("smtp1@gmail.com" => 2),
    array("smtp2@gmail.com" => 4),
    array("smtp3@gmail.com" => 5)
);        

/*When I Iterate the $emails array now */
//pre($smtp);
$counter=0;
foreach($emails as $email_key=>$email_value){            
    $smtp_detail=$smtp[$counter];            
    send_email($email_value,$smtp_detail);
    $counter++;  
}

As of now its working fine, but its not working with the limit per SMTP email.

How do I apply limit on email as per smtp as defined in $stmp ? It should only fire 11 emails, as that is the total count (2 + 4 + 5 = 11), so smtp1@gmail.com should fire 2 emails, then smtp2@gmail.com should fire 4, and mtp3@gmail.com should fire 5.

Expected Output

$output_expected = array(
     test1@gmail.com => 'ok', 'smtp_used' => smtp1@gmail.com,
     test2@gmail.com => 'ok', 'smtp_used' => smtp2@gmail.com,
     test3@gmail.com => 'ok', 'smtp_used' => smtp3@gmail.com,
     test4@gmail.com => 'ok', 'smtp_used' => smtp1@gmail.com,
     test5@gmail.com => 'ok', 'smtp_used' => smtp2@gmail.com,
     test6@gmail.com => 'ok', 'smtp_used' => smtp3@gmail.com,
     test7@gmail.com => 'ok', 'smtp_used' => smtp2@gmail.com,
     test8@gmail.com => 'ok', 'smtp_used' => smtp3@gmail.com,
     test9@gmail.com => 'ok', 'smtp_used' => smtp2@gmail.com,
     test10@gmail.com => 'ok', 'smtp_used' => smtp3@gmail.com,
     test11@gmail.com => 'ok', 'smtp_used' => smtp3@gmail.com
);

So total email should be fired only 11 as my smtp limit count is 11 in the order I have specified

Fetch the first element from your $smtp array through array_shift() - this removes the first element from the array and returns that. Use reset() to get the value (which is the limit) and key() to get the key (which is the SMTP email).

Inside the loop, check if the counter has reached the limit - if it has, shift out the next value-pair, see if any was returned (if its null , there were no more values and we break out of the loop). If you got a valid result, use reset() and key() again.

$counter = 0;

$smtp_values = array_shift($smtp);
$limit = reset($smtp_values);
$smtp_email = key($smtp_values);

foreach ($emails as $email_key=>$email_value) {
    send_email($email_value, $smtp_email);

    $counter++;

    if ($limit == $counter) {                    // Check if the limit was reached
        $counter = 0;                            // Reset the counter
        $smtp_values = array_shift($smtp);       // Get the next pair of values

        // If there are no more values in the $smtp array, break out of the loop
        if (!$smtp_values) {
            break;
        }

        $limit = reset($smtp_values);            // Get the limit
        $smtp_email = key($smtp_values);         // Get the email
    }
}

Alternatively, you can do it through loops as well for earlier versions of PHP. Loop over the $smtp array, and for each iteration, get the email by using key() and the limit by using array_shift() . As before, this removes the first element of the array, meaning that when you use it enough times, there will not be anything else to loop.

Inside the outer loop, loop over your $emails and pass the values through to the function. Check if the limit has been reached, and use continue 2 to use continue on the outer loop.

$counter = 0;

foreach ($smtp as $s) {
    $smtp_email = key($s);
    $limit = array_shift($s);

    foreach ($emails as $email_value) {
        send_email($email_value, $smtp_email);
        array_shift($emails);
        $counter++;

        if ($counter == $limit) {
            $counter = 0;
            continue 2;  // Continue the outer loop
        }
    }
}

We can prepare a send list array with email => smtp using foreach and array_fill and array_combine.

Once this list is done the array can be iterated and emails sent with the corresponding smtp.

$emails = array(            
    "test1@gmail.com",
    "test2@gmail.com",
    "test3@gmail.com",
    "test4@gmail.com",
    "test5@gmail.com",
    "test6@gmail.com",
    "test7@gmail.com",
    "test8@gmail.com",
    "test9@gmail.com",
    "test10@gmail.com",
    "tes11@gmail.com",
    "test12@gmail.com",
    "test13@gmail.com",
    "test14@gmail.com",
    "test15@gmail.com",
    "test16@gmail.com",
    "test17@gmail.com",
    "test18@gmail.com",
    "test19@gmail.com",
    "test20@gmail.com",
);

/*I have set smtp array with Its Daily Limit Count*/
$smtps=array(
    array("smtp1@gmail.com" => 2),
    array("smtp2@gmail.com" => 4),
    array("smtp3@gmail.com" => 5)
);        

$start =0;
$send =[];
foreach($smtps as $sub){
    foreach($sub as $smtp => $count){
        $send = array_merge($send, array_combine(array_slice($emails, $start, $count),array_fill(0, $count, $smtp)));
        $start += $count;
    }
}
var_dump($send);

Gives:

array(11) {
  ["test1@gmail.com"]=>
  string(15) "smtp1@gmail.com"
  ["test2@gmail.com"]=>
  string(15) "smtp1@gmail.com"
  ["test3@gmail.com"]=>
  string(15) "smtp2@gmail.com"
  ["test4@gmail.com"]=>
  string(15) "smtp2@gmail.com"
  ["test5@gmail.com"]=>
  string(15) "smtp2@gmail.com"
  ["test6@gmail.com"]=>
  string(15) "smtp2@gmail.com"
  ["test7@gmail.com"]=>
  string(15) "smtp3@gmail.com"
  ["test8@gmail.com"]=>
  string(15) "smtp3@gmail.com"
  ["test9@gmail.com"]=>
  string(15) "smtp3@gmail.com"
  ["test10@gmail.com"]=>
  string(15) "smtp3@gmail.com"
  ["tes11@gmail.com"]=>
  string(15) "smtp3@gmail.com"
}

To send emails just loop and send:

foreach($send as $mail => $smtp){
    send_email($mail, $smtp);
}


If the order is important then we can flatten smtp array to make the prepare easier.

//Flatten smtp array
foreach($smtps as &$sub){
    foreach($sub as $smtp => &$count){
        $newsmtp[$smtp] = $count;
    }
}

$start =0;
$send =[];

//Loop while there are $count left
while(array_sum($newsmtp)){
    foreach($newsmtp as $smtp => &$count){
        if($count){
            $send = array_merge($send, array_combine(array_slice($emails, $start, 1), [$smtp]));
            $count--;
            $start++;
        }
    }
}

var_dump($send);

Gives:

array(11) {
  ["test1@gmail.com"]=>string(15) "smtp1@gmail.com"
  ["test2@gmail.com"]=>string(15) "smtp2@gmail.com"
  ["test3@gmail.com"]=>string(15) "smtp3@gmail.com"
  ["test4@gmail.com"]=>string(15) "smtp1@gmail.com"
  ["test5@gmail.com"]=>string(15) "smtp2@gmail.com"
  ["test6@gmail.com"]=>string(15) "smtp3@gmail.com"
  ["test7@gmail.com"]=>string(15) "smtp2@gmail.com"
  ["test8@gmail.com"]=>string(15) "smtp3@gmail.com"
  ["test9@gmail.com"]=>string(15) "smtp2@gmail.com"
  ["test10@gmail.com"]=string(15) "smtp3@gmail.com"
  ["tes11@gmail.com"]=>string(15) "smtp3@gmail.com"
}

This can the be iterated and sent as suggested above.
https://3v4l.org/b4fQf

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM