0

I have an array of items. There are two "types" or items: a heading row, and a regular row. I want to print the heading only if there are any "regular" rows under it (before the next heading).

(This is a simplification - in practice I wont be able to look at the next item from in the current iteration).

To solve this, I used buffer control. I clear and start the buffer at each heading row, and in each regular row I flush the buffer. So the heading wont print if there is a heading after it (buffer will be cleaned) and will be flushed to user if there is a regular row to "flush" it out.

(psudeo code)

for i in array:
     if i is heading:
          ob_end_clean();
          ob_start();
          echo "header $i";
     else:
          ob_end_flush();
          echo "regular $i"

This works great.

Problem is, I have an option to download the page as a PDF and this broke it. The way it works is if the pdf flag is on, at the top of the page, buffer was started and at the bottom of the code, the buffer was dumped into a variable and sent to the pdf api as a string. Now, the buffer is sent to the user at ob_end_flush() which produces this error when I try to download the pdf:

cannot modify header information - headers already sent.

I like my solution but is there a way to make it work? Or is it a bad solution to begin with? thanks

danielb
  • 878
  • 4
  • 10
  • 26
  • Instead of using output buffer, can you just build up a string and echo it at the end? – Don't Panic Apr 20 '15 at 19:17
  • @Don'tPanic That wastes a ton of memory, and so does buffering forever. – Brad Apr 20 '15 at 19:18
  • can you remove the header errors on clicking for pdf option i.e. identify that the pdf option has been clicked & after it ob_clean used to remove the header error – lakshman Apr 20 '15 at 19:20
  • @Don'tPanic that doesn't work since in the iteration of the heading, I dont know whether to include that i in the string or not – danielb Apr 20 '15 at 19:22
  • @Brad Yes, but won't it all have to be sent to the PDF converter as a string anyway, or is there a different way to do that? – Don't Panic Apr 20 '15 at 19:25
  • Seems like you could hold each item until the next iteration, then decide what to do with it. – Don't Panic Apr 20 '15 at 19:36
  • @Don'tPanic That depends on what is doing the converter. If the converter supports STDIN, you can stream directly to it. It will provide back pressure if needed, or it may choose to buffer the whole thing. It might also just start conversion immediately... who knows, it's up to the downstream application. – Brad Apr 20 '15 at 19:36

2 Answers2

0

Instead of outputing to buffer, output to a file buffer instead. At then end just send the whole file (it is a bit tricky but it should work fine if you manage the redirections correctly):

pseudo-code:

for i in array:
     if i is heading:
          // output to file buffer
          echo "header $i";
     else:
          // stop output to file buffer
          echo "regular $i"
Community
  • 1
  • 1
Nikos M.
  • 8,033
  • 4
  • 36
  • 43
0

My suggestion is, even though you can't look at the next item, I think you could keep track of the previous item. I think this should work regardless of your output method.

$previous = '';
foreach ($rows as $row) {
    if ($row == 'header') {
        // Wait to print header rows depending on what the next row is.
        $previous = $row;
    } else {
        // For regular rows, print the preceding header row (if there is one.)
        echo $previous;
        echo $row; // Print the regular row.
        $previous = ''; // Then clear the saved header row.
    }
}
Don't Panic
  • 41,125
  • 10
  • 61
  • 80