在我们的PHP应用程序中,有一个函数可以在收集发送过程的日志时使用PHPMailer
发送邮件:
function sendWithLog(PHPMailer $mail, &$debug_log, $log_level = PHPMailer_SMTP::DEBUG_CONNECTION) {
$debug_log = [];
$mail->SMTPDebug = $log_level ?: PHPMailer_SMTP::DEBUG_CONNECTION;
$mail->Debugoutput = function($message) use(&$debug_log) {
$debug_log[] = $message;
};
$sent = $mail->send();
$debug_log = !$sent
? $mail->ErrorInfo
. ($debug_log ? "\n" . implode("\n", $debug_log) : "")
: "";
return $sent;
}
因此,通过引用传递的变量$debug_log
首先应初始化为空数组,最后将其制成字符串。
如果再次调用该函数,并将其作为上一次调用的$debug_log
的{{1}}传递,我会看到此错误:
PHP致命错误:未捕获错误:字符串不支持[]运算符
但是,在用$debug_log
语句绑定到闭包之前,该变量仍应初始化为空数组,因此我真的不明白该错误怎么发生。
我尝试使用简化版本的代码here重现此行为,但似乎并未触发错误。
编辑:
我通过更改如下功能解决了这个问题:
use()
但是,我仍然想知道它最初如何触发错误。
用法示例如下:
function sendWithLog(PHPMailer $mail, &$debug_log, $log_level = PHPMailer_SMTP::DEBUG_CONNECTION) {
$messages = []; // <-- different variable for collecting the log messages!
$mail->SMTPDebug = $log_level ?: PHPMailer_SMTP::DEBUG_CONNECTION;
$mail->Debugoutput = function($message) use(&$messages) {
$messages[] = $message;
};
$sent = $mail->send();
$debug_log = !$sent
? $mail->ErrorInfo
. ($messages ? "\n" . implode("\n", $messages) : "")
: "";
return $sent;
}
编辑2
这是示例堆栈跟踪:
// $users -> query result from database
while($user = $users->fetch()) {
// build mail and then
$sent = sendWithLog($mail, $mail_log);
// here $mail_log should be initialized to NULL the first time by the PHP engine
// and in subsequent calls it is the log string of the previous call which should be
// reset to [] first thing inside the function call
if(!$sent) {
error_log("ERROR SENDING MAIL: $mail_log");
}
}
答案 0 :(得分:1)
刚刚太久了,无法发表评论,所以让我在这里输入:
考虑到您的示例,我唯一想到的就是-我不确定这里的内部工作原理,但是无论如何,我还是要解释一下-
您将$mail->Debugoutput
设置为可调用项,将一项附加到$debug_log
。现在,在函数结束时,将$debug_log
设置为字符串($debug_log = !$sent
等),在设置字符串期间,可能会发生以下情况:当由于某种原因而发生字符串串联时发生的implode()
,$mail->Debugoutput
又被调用了(可能是在__toString()
期间吗?),它试图将数组项附加到$debug_log
,这是不可能的,因为它被设置为字符串。因此是错误。