【问题标题】:How can I use an output buffer inside a foreach loop?如何在 foreach 循环中使用输出缓冲区?
【发布时间】:2020-06-16 19:15:52
【问题描述】:

我正在构建一个简单的类,它可以通过组合模板包含和我在输出缓冲区中提取的数据数组来为我的电子邮件正文生成 html。

问题是,当我在循环中使用输出缓冲区运行该方法时(根据用户信息创建电子邮件),我收到以下错误:

ob_end_clean(): 删除缓冲区失败。没有要删除的缓冲区... 无法修改标头信息 - 标头已由 ...

我需要更改哪些内容才能使其同时适用于单个电子邮件和循环内?

电子邮件类

<?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 );
}
?>

【问题讨论】:

  • @bestprogrammerintheworld 不,不幸的是我已经尝试过了
  • ob_end_clean() 关闭输出缓冲。你确定你不是说 ob_clean() 吗?
  • 如果你能得到模板来构建一个字符串并返回它而不是依赖输出缓冲会更好。
  • 3v4l.org/ALSkO 你开始缓冲所以不应该抛出错误。

标签: php buffer


【解决方案1】:

让我们看看输出缓冲区是如何工作的:

// 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; 
}

【讨论】:

    【解决方案2】:
     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();
       }
    

    希望对你有帮助

    【讨论】:

    • 试过了,还是报错:Cannot modify header information - headers already sent by ...
    • 检查您的代码在
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多