0

我正在使用 foreach 循环发送邮件,以在控制器的 codeigniter 方法中获取收件人信息,并且,如果发送了邮件,我将收件人表中的收件人状态更新为“已发送”。

在同一控制器的另一种方法中(使用相同的模型),我得到了未发送邮件的数量,但是如果我在发送邮件时尝试获取未发送邮件的数量,它会等到 foreach 循环完成。

在 foreach 循环中发送邮件时,如何连续获取未发送邮件的数量?

recipients table
    id int 11
    recipient_id int 11
    mail_id int 11
    sent tinyint 1
    failed tinyint 1

$recipients = $this->MMails->GetRecipients($mail_id);
foreach($recipients as $recipient) {
    //send message using swift
    if($message_sent) {
        $this->MMails->MarkAsSent($recipient_id);//this recipient table gets updated actually, but I can't read the new COUNT value until this loop finished
    }
}

从模型:

 function GetNumOfQueued() {//Get number of queued mails
    $query = $this->db->query("SELECT COUNT(id) as num_of_queued
        FROM recipients 
        WHERE sent = 0");
    return $query->row()->num_of_queued;
}//GetNumOfQueued

 function MarkAsSent($recipient_id) {//Update mail recipient status to sent
    $this->db->set('sent', 1);
    $this->db->where('id', $recipient_id);
    $this->db->limit(1);
    $this->db->update('recipients');

}//MarkAsSent

简而言之,PHP 在循环完成之前不会响应,并且当循环处于活动状态时,我无法打开应用程序中的任何其他页面。

我本地 php.ini 中的设置是 output_buffering = Off

4

3 回答 3

0

我建议将未发送邮件的数量保留在数据库中并使用查询获取它。

于 2012-11-08T15:48:09.697 回答
0

你不能只用一个计数器吗?

$recipients = $this->MMails->GetRecipients($mail_id);
$messages_to_send = count($recipients);
foreach($recipients as $recipient) {
    //send message using swift
    if($message_sent){
        $messages_to_send--; 
        $this->MMails->MarkAsSent($recipient_id);
    }
}

输出缓冲应该可以解决问题:

http://php.net/manual/en/book.outcontrol.php

它将在循环运行时允许其他执行。

以下是处理循环时在屏幕上输出 ob 的示例:

if (ob_get_level() == 0) ob_start();

for ($i = 0; $i<10; $i++){

        echo "<br> Line to show.$i";
        echo str_pad('',4096)."\n";    

        ob_flush();
        flush();
        sleep(2);
}

echo "Done.";
ob_end_flush();

-http://us1.php.net/manual/en/function.flush.php#54841


if (ob_get_level() == 0) ob_start();

$recipients = $this->MMails->GetRecipients($mail_id);
$messages_to_send = count($recipients);
foreach($recipients as $recipient) {
    //send message using swift
    if($message_sent){
        $messages_to_send--; 
        $this->MMails->MarkAsSent($recipient_id);
        echo "<br> Emails left to send: .$messages_to_send";
        echo str_pad('',4096)."\n";    
        ob_flush();
        flush();
    }
}
echo "All emails have been sent.";
ob_end_flush();
于 2012-11-08T16:09:25.957 回答
0

PHP 类实例是根据请求创建的,因此如果您希望能够在它仍在运行时获取信息,您将需要将数据写入 MySQL 中的表或使用类似Memcachedor的东西APC

于 2012-11-08T15:48:58.963 回答