Как я могу использовать выходной буфер внутри foreach l oop? - PullRequest
0 голосов
/ 16 июня 2020

Я создаю простой класс, который может генерировать html для тела моего сообщения электронной почты с помощью комбинации включения шаблона и массива данных, которые я извлекаю внутри выходного буфера. Я запускаю метод с буфером вывода внутри al oop (для создания электронных писем на основе информации о пользователе). Я получаю следующую ошибку:

ob_end_clean (): не удалось удалить буфер. Нет буфера для удаления ... Невозможно изменить информацию заголовка - заголовки уже отправлены ...

Что мне нужно изменить, чтобы он работал как для одного электронного письма, так и внутри al oop?

Класс электронной почты

<?php
class Email {

   protected $_html;

   protected $_data;

   public function __construct( array $email_data = [] ) {
      $this->_data = $email_data;
      $this->generate_html();
   }

   protected function generate_html() {
      $template_path = 'path/to/email-template.php';
      ob_start();
      extract( $this->_data );
        include $template_path;
      $this->_html = ob_get_contents();
      ob_end_clean();
   }

   public send( $to = [] ) {
      mail( $to, 'Test email', $this->_html, ['Content-Type: text/html; charset=UTF-8'] );
   }

}
?>

Проверка моего кода:

<?php 
function send_test_email( $id, $to ) {
   $email_data = [
      'id'    => $id,
      'name'  => 'Joe',
      'price' => '30.00'
   ];
   $email = new Email( $email_data );
   $email->send( $to );
}

// Works
send_test_email( 122, 'joe@example.com' );

// Does not work
// ob_end_clean(): failed to delete buffer. No buffer to delete in
// Cannot modify header information - headers already sent by ...
foreach ( $users as $user ) {
   send_test_email( $user->id, $user->email );
}
?>

Ответы [ 2 ]

1 голос
/ 16 июня 2020

Давайте посмотрим, как работают буферы вывода:

// Works
send_test_email( 122, 'joe@example.com' );

/*
    When you have executed send_test_email() above the method generate_html() is 
    executed and ob_start and ob_end_clean() is executed. This means that the output 
    buffer is initiated and stopped with ob_end_clean(). 

    When output buffer is ended it is sent to the client (browser).
*/

//If you do the same again...
send_test_email( 122, 'joe@example.com' );

/*
  ...this won't work because output buffer is sent to the browser. After this is done
  you are not able to modify header information. Because you cannot modify header 
  information you can not start a new output buffer either.

  That is why you get the error below:

  ob_end_clean(): failed to delete buffer. No buffer to delete in
  Cannot modify header information - headers already sent by ...
*/

Чтобы решить эту проблему, я бы попробовал что-то вроде этого:

Убрать ob_start() и ob_end_clean() вне класса и удалите их из метода generate_html()

protected function generate_html() {
    $template_path = 'path/to/email-template.php';
    extract( $this->_data );
    include $template_path;
    $this->_html = ob_get_contents();
}

Тестирование вашего кода:

ob_start();
send_test_email( 122, 'joe@example.com' );

foreach ( $users as $user ) {
   send_test_email( $user->id, $user->email );
}
ob_end_clean();

ОБНОВЛЕНИЕ Вы можете решить эту проблему не возиться с буферами вывода, что-то вроде:

protected function generate_html() {
    $template_path = 'path/to/email-template.php';
    extract( $this->_data );

    //requires the template file to have a return to able to store the
    //content in a variable
    //
    //Look at $foo = include 'return.php'; 
    //at https://www.php.net/manual/en/function.include.php
    $this->_html = include $template_path; 
}
0 голосов
/ 16 июня 2020
 protected function generate_html() {
      $template_path = 'path/to/email-template.php';
      ob_start();
      extract( $this->_data );
        include $template_path;
      $this->_html = ob_get_clean();  //use ob_get_clean()  instead of ob_get_contents();
   }

Надеюсь, это вам поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...