PHP output buffer control - php

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

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"

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.
}
}

Related

Overwrite values in for-loop PHP

How can i print values in same place when i echo the statement instead of printing the values in the same/next line (if using br tag). This is a sample for-loop
for($i=0;$i<10;$i++)
{
echo $i;
}
The output will be:
0123456789
But I want my output to be the one as shown below as it should overwrite values in the same place.
9
I will display all the values slowly one by one using timer or sleep but my objective here is to overwrite the previous value or display it in the same place.
I'm sorry, but you can't do it.
If you want to change the output in the browser itself, after you flushed the buffer, you have to use JS.
Think of it this way:
When you echo, you put some values in the buffer stream. When the buffer is flushed, you see the printed value in the browser.
You can manage the buffer, flush it, clean it, change it, but you can't change whats already out there.
I hope that helps some how.
Look at this link for more information about stream output:
Output Control

Shall I use output buffering (ob_start) or not

I have amended my PHP code in order to avoid using output buffering after finding out that it denotes a poor coding pattern. But still am using it where it is needed inevitably.
But, some articles say that using output buffering is beneficial as it combines the output into one , by default the output is broken into html and headers separately and is then displayed on the browser, but output buffering eliminates this breakage process, thus augmenting the speed of output display to the end user.
All this article stuff has left me in a dilemma to use or completely avoid output buffering. Am not sure if am completely right about its working and the points I have mentioned.
So please guide me accordingly.
There are times where the use of output buffering is a good thing to use, but to use it as lots of people do (the lazy way of not having to send headers before output for example) is not the right time.
The example you give, I do not know much about, but if its optimal, it might be one of the times where its good to use.
Its not forbidden to use ob_start(), its just the "wrong way" to use it the way I stated earlier.
The optimization you mention feels like a very low-level optimization, you might get a tad bit 'quicker' output, but there is usually a lot of other optimizations in a standard php-script that could speed it up before that is worth looking at!
edit:
Example of a small script that don't use send headers before output vs one that do:
<?php
$doOutput = true;
$doRedirect = true;
$output = "";
if($doOutput == true){
// $doOutput is true, so output is supposed to be printed.
$output = "Some output yay!";
}
if($doRedirect == true){
// but $doRedirect is also true, so redirect will be done.
header("location:anotherpage.php"); // This will not produce an error cause there was no output!
exit();
}
// The echo below will not be printed in the example, cause the $doRedirect var was true.
echo $output;
Instead of (this case will produce a header sent after output error):
<?php
$doOutput = true;
$doRedirect = true;
if($doOutput == true){
//Output will be printed, cause $doOutput is true.
echo "Some output yay!";
}
if($doRedirect == true){
// but $doRedirect is also true, so redirect will be done.
header("location:anotherpage.php"); // This will produce an error cause output was already printed.
exit();
}
edit2: Updated with a more obvious example!

Loading results into the buffer without echoing to the browser

How can I load loop results into a buffer using the PHP output control functions without echoing the results to the browser? In essence, what I'm trying to do is call results from the buffer as opposed to echoing my way through the loop "as it goes". Is it possible to do this? Any help appreciated. Thanks!
Use ob_get_contents to get the buffer contents without sending them.
To clean out the buffer call ob_end_clean
To do both in one step call ob_get_clean
An example would be
ob_start();
foreach ($results as $result){
include("tmplate/to/render/a/result.php");
}
$resultHTML = ob_get_clean();
Then later.
<div class='left-rail'><?= $resultHtml ?></div>
It's still not clear what you mean, but here's an answer based on past experience with php programmers: PHP is a full programming language, so you can build complex data structures without producing any output. If you're reading rows from a database, you can read them into an array, do whatever you want with the array, then produce output when you're ready.
If you're generating output by scanning through the array in lots of steps, you can gradually build up a string (or more, if that's necessary in your case) and again output them when you know what you want to do.
Something along these lines:
$output = "";
foreach ($my_array as $row) {
$output .= "<li>".$row."</li>\n";
// plus various checks etc.
}
Am I getting the idea of what you're after?

PHP Output buffering contains something before script starts

i have a site, where i buffer some output with
ob_start();
...
and it worked fine until today i updated my debian from an older php5.3 to the latest php5.3.3-7+squeeze8
Now i sometimes have something in the output buffer before i call it the first time
please don't answer things like
"header must be called before any output is sent."
(I know, I work a lot with output buffers)
when i set an extra ob_get_clean(); at the very first line of my script, it works
<?
ob_get_clean();
it seems, like php is creating some output beforehand
if i put the first line
<? print_r(ob_get_clean()); ?>
then i see, that there is an empty string already in the buffer:
""
on all other pages it isn't, there ob_get_clean(); contains
null
is it possible you have some " " in front of your <?php somewhere? or wrong file encoding issue its usually some kind of that nature, check your files and include files.
Now i sometimes have something in the output buffer before i call it
the first time
It'll be much easier if you give us some info about that mysterious data.
perhaps a case of BOM character?
more info here
i found it:
i had no invisible character in front, it was something different: i called ob_end_clean() one time too much:
this was my code, inside a function i call:
function print_something(){
ob_start();
echo some stuff...
echo ob_get_clean();
ob_end_clean(); // this was the bug!
}
it seems, that you can clear your main output buffer ;)

How to clear previously echoed items in PHP

In php, is there any way to clear/remove all previously echoed or printed items?
For example:
<?php
echo 'a';
print 'b';
// some statement that removes all printed/echoed items
echo 'c';
// the final output should be equal to 'c', not 'abc'
?>
My script uses the include function. The included files are not supposed to echo anything. Just in case someone (ex = hacker) tries, I need a way to remove.
<?php
ob_start();
echo 'a';
print 'b';
// some statement that removes all printed/echoed items
ob_end_clean();
echo 'c';
// the final output is equal to 'c', not 'abc'
?>
Output buffering functions
The output buffering functions are also useful in hackery to coerce functions that only print to return strings, ie.
<?php
ob_start();
var_dump($myVar);
$data = ob_get_clean();
// do whatever with $data
?>
while #monoxide is right, its better to find more intuitive ways of doing the same. e.g.:
<?php
$val_to_print = $a;
if( $need_to_change==true )
$val_to_print = $b;
// when you are sure you won't have to change again...
echo $val_to_print;
?>
Cheers,
jrh
Ideally, you shouldn't output anything that you don't ultimately want printed. Keep your logic separate from your presentation for less frustration.
That being said, you can consult the Output Buffering options within PHP.
If it is debug output and program status information you are worried about maybe trigger_error may be nearer to what you need, such as:
trigger_error ("Attempting to load report #{$report_id}.", E_USER_NOTICE);
When your script is in production it wont show up any errors as generally they are disabled or logged. It's also best to do fatal errors this way with E_USER_ERROR rather than using die ().
ob_start ();
require ($filename);
$html = ob_get_clean ();
The above will also include a file and give you its contents as a string.
Caveat: Ditching the buffer will also ditch any error messages thrown up, making debugging (potentially) a nightmare.
If a hacker let's say has access to your PHP file, he will also be able to remove the statement clearing the output buffer.
If you are doing this because you are letting your users upload PHP scripts, let me tell you that this is an extremely bad idea.
In both cases, doing what you are asking for adds 0 security.

Categories