Неустранимая ошибка при передаче параметра по ссылке

В нашем приложении 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 $debug_log предыдущего вызова, я вижу эту ошибку:

Неустранимая ошибка PHP: необработанная ошибка: оператор [] не поддерживается для строк

Тем не менее, переменная по-прежнему должна быть инициализирована как пустой массив перед привязкой к закрытию с помощью 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;
}

Однако мне все еще интересно, как это могло спровоцировать ошибку в первую очередь.

Пример использования следующий:

// $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");
}
}

РЕДАКТИРОВАТЬ 2

Вот пример трассировки стека:

PHP Fatal error:  Uncaught Error: [] operator not supported for strings in /opt/agews64/www/includes/class/AGEws/Mail.php:134
Stack trace:
0 /opt/agews64/www/includes/class/PHPMailer/SMTP.php(220): AGEws_Mail::{closure}('CLIENT -> SERVE...', 1)
1 /opt/agews64/www/includes/class/PHPMailer/SMTP.php(991): PHPMailer_SMTP->edebug('CLIENT -> SERVE...', 1)
2 /opt/agews64/www/includes/class/PHPMailer/SMTP.php(885): PHPMailer_SMTP->client_send('QUIT\r\n')
3 /opt/agews64/www/includes/class/PHPMailer/SMTP.php(827): PHPMailer_SMTP->sendCommand('QUIT', 'QUIT', 221)
4 /opt/agews64/www/includes/class/PHPMailer.php(1721): PHPMailer_SMTP->quit()
5 /opt/agews64/www/includes/class/PHPMailer.php(670): PHPMailer->smtpClose()
6 /opt/agews64/www/includes/class/AGEws/Mail.php(147): PHPMailer->__destruct()
7 /opt/agews64/www/includes/class/AGEws/Mail.php(118): AGEws_Mail::sendWithLog(NULL, 'SMTP Error: Dat...', 3)
8 /opt/agews64/www/includes/class/AGEws/Cron/Import.php(154): AGEws_Mail::prepareAndSendWithLog('SMTP Error: Dat...', Array, 'Risu in /opt/agews64/www/includes/class/AGEws/Mail.php on line 134

-1

Решение

Это было просто слишком долго для комментария, поэтому позвольте мне напечатать его здесь:

Единственное, что я могу подумать о рассмотрении вашего примера — и я не уверен насчет внутренних органов на работе, но позвольте мне все равно попытаться объяснить — это:

Ты устанавливаешь $mail->Debugoutput быть вызываемым, который добавляет элемент к $debug_log, Теперь, когда в конце вашей функции вы устанавливаете $debug_log быть строкой ($debug_log = !$sent так далее.), в течение что установка строки, может случиться так, что во время implode() это происходит, когда конкатенация строк происходит по какой-то причине $mail->Debugoutput вызывается снова (может быть, во время __toString()?), который пытается добавить элемент массива к $debug_log, что невозможно, потому что он задан как строка. Отсюда и ошибка.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]