SELECT语句找不到刚刚插入同一http请求的记录

时间:2016-03-07 14:57:23

标签: php mysql mysqli

我有一个简单的类,有两个方法:添加和处理。

require_once('MailQueue.config.php');
require_once('class.phpmailer.subclass.php');

class MailQueue {
    private $dbServer;
    private $dbName;
    private $dbUsername;
    private $dbPassword;
    private $mailLimit;
    private $mailLimitTimeUnit;
    private $db;

    function __construct() {
        global $CONFIG;

        // Set database connection variables
        $this->dbServer = $CONFIG['dbServer'];
        $this->dbName = $CONFIG['dbName'];
        $this->dbUsername = $CONFIG['dbUsername'];
        $this->dbPassword = $CONFIG['dbPassword'];

        // Set app settings
        $this->mailLimit = $CONFIG['mailLimit'];
        $this->mailLimitTimeUnit = $CONFIG['mailLimitTimeUnit'];

        // Connect to database
        $this->db = new mysqli($this->dbServer, $this->dbUsername, $this->dbPassword, $this->dbName);

        if($this->db->connect_error) {
            die("Error connecting to MailQueue.<br />".$this->db->connect_error);
        }
    }

    function add($data) {
        $sqls = "";

        foreach($data as $d) {
            $sqls .= "INSERT INTO mailqueue (".
                        "desiredSendTime, ".
                        "fromName, ".
                        "fromAddress, ".
                        "toName, ".
                        "toAddress, ".
                        "subject, ".
                        "bodyHtml ".
                    ") VALUES (".
                        "'".$d['sendAt']."',".
                        "'".$d['fromName']."',".
                        "'".$d['fromAddress']."',".
                        "'".$d['toName']."',".
                        "'".$d['toAddress']."',".
                        "'".$d['subject']."',".
                        "'".$d['body']."'".
                    ");";
        }

        $insertIds = Array();

        if(!$this->db->multi_query($sqls)){
            die("Error adding emails to mailqueue: (".$this->db->errno.") ".$this->db->error);
        }

        // fetch insert ids
        do {
            $insertIds[] = $this->db->insert_id;
        } while($this->db->more_results() && $this->db->next_result());

        return $insertIds;
    }

    function processQueue($numberOfMessages, $preferredEmailIds="") {
        // Get number of emails already sent in this timeframe

        // Do not check for the last timeUnit, but for the timeUnit we're currently in, e.g.
        // if timeUnit = 'hour', count the processed emails in de current hour, not in the last 60 minutes.
        switch($this->mailLimitTimeUnit) {
            case 'year':
                $startOfCurrentTimeframe = date('Y-01-01 00:00:00');
                break;
            case 'month':
                $startOfCurrentTimeframe = date('Y-m-01 00:00:00');
                break;
            case 'day':
                $startOfCurrentTimeframe = date('Y-m-d 00:00:00');
                break;
            case 'hour':
                $startOfCurrentTimeframe = date('Y-m-d H:00:00');
                break;
            case 'minute':
                $startOfCurrentTimeframe = date('Y-m-d H:i:00');
                break;
            default:
                $startOfCurrentTimeframe = '';
        }

        if($startOfCurrentTimeframe != '') {
            $successCounter = 0;

            $sql =  "SELECT ".
                        "COUNT(*) AS currentCount ".
                    "FROM ".
                        "mailqueue ".
                    "WHERE ".
                        "actualSendTime BETWEEN '".$startOfCurrentTimeframe."' AND NOW()";

            if(!($stmt = $this->db->prepare($sql))) {
                die("Prepare failed: (".$this->db->errno.") ".$this->db->error);
            }

            if(!($stmt->execute())) {
                die("Execute failed: (".$stmt->errno.") ".$stmt->error);
            }

            $result = $stmt->get_result();
            $row = $result->fetch_assoc();
            $currentCount = $row['currentCount'];
            $spaceLeft = $this->mailLimit - $currentCount;

            // Don't exceed the mail limits!
            if($spaceLeft < $numberOfMessages){
                $numberOfMessages = $spaceLeft;
            }

            // In case of preferred emails, add an explicit filter to accomplish this
            if($preferredEmailIds!=""){
                $preferredEmailsOnly = "AND id IN (".implode(',', $preferredEmailIds).") ";
            } else {
                $preferredEmailsOnly = "";
            }

            // Process new emails
            $sql =  "SELECT ".
                        "* ".
                    "FROM ".
                        "mailqueue ".
                    "WHERE ".
                        "desiredSendTime < NOW() ".
                        "AND actualSendTime IS NULL ".
                        $preferredEmailsOnly.
                    "ORDER BY ".
                        "desiredSendTime, ".
                        "id ".
                    "LIMIT ?";

            if(!($stmt = $this->db->prepare($sql))) {
                die("Prepare failed: (".$this->db->errno.") ".$this->db->error);
            }

            if (!$stmt->bind_param("i", $numberOfMessages)){
                die("Binding parameters failed: (".$stmt->errno.") ".$stmt->error);
            }

            if (!$stmt->execute()) {
                die("Execute failed: (".$stmt->errno.") ".$stmt->error);
            }

            $result = $stmt->get_result();

            if($result->num_rows > 0) {
                $successCounter = 0;
                $sqls = "";

                while($row = $result->fetch_assoc()) {
                    $msg = new themedMailer();

                    $msg->From = $row['fromAddress'];
                    $msg->FromName = $row['fromName'];
                    $msg->Subject = $row['subject'];
                    $msg->Body = $row['bodyHtml'];

                    $msg->IsMail();

                    $msg->AddAddress($row['toAddress'], $row['toName']);

                    if($msg->Send()) {
                        $successCounter++;

                        // Save the time of sending to the email in the database
                        $sqls .= "UPDATE mailqueue SET actualSendTime = NOW() WHERE id = ".$row['id'].";";
                    } else {
                        die("Sending mail failed: ".$this->ErrorInfo);
                    }
                }

                // Update the sent emails
                if(!$this->db->multi_query($sqls)){
                    die("Failed updating records for sent emails; these emails will be sent again because of this error.");
                }
            }

            $stmt->close();
        }

        return $successCounter;
    }
}

如果我使用单独的http请求来调用addprocess函数,则它可以正常工作。 add函数在表中添加了一些记录,process函数处理来自同一表的一些记录(不一定是相同的记录)。 如果我尝试将两者合并以使process处理由add插入的记录,则process函数根本找不到由{{1}插入的记录功能。一些代码解释了我一直在尝试的内容:

此代码可以正常工作:

HTTP请求1:

add

HTTP请求2:

ERROR_REPORTING(E_ALL);

require_once('../MailQueue.class.php');

$queue = new MailQueue();

$currentTime = date('YmdHis');
$data = Array();

$num = 2000;

for($i=1; $i<=$num; $i++) {
    $data[$i] = Array();
    $data[$i]['sendAt']      = date('Y-m-d H:i:s');
    $data[$i]['fromName']    = 'John Doe';
    $data[$i]['fromAddress'] = 'john@doe.com';
    $data[$i]['toName']      = 'Jane Doe';
    $data[$i]['toAddress']   = 'jane@doe.com';
    $data[$i]['subject']     = 'Test message MailQueue '.$currentTime;
    $data[$i]['body']        = 'Test message MailQueue '.$currentTime;
}

$queue->add($data);

echo "Added ".$num." new emails to be sent";

以下代码不起作用,因为ERROR_REPORTING(E_ALL); require_once('../MailQueue.class.php'); $try = 50; $queue = new MailQueue(); echo "Trying to send ".$try." emails.<br />"; $counter = $queue->processQueue($try); echo "Sent ".$counter." emails."; if($counter < $try) { echo " Not all desired emails were sent, so the mail limit was probably reached. Please try again later."; } 函数中的SELECT查询不返回任何记录:

只有1个HTTP请求:

process

任何人都可以解释为什么组合这两个功能不起作用? Autocommit是1,我试图明确提交,但无济于事。

0 个答案:

没有答案