When to use ob_start() and ob_end_flush()

Like your style Joe :slight_smile:

Off Topic:

Salathe. I always like your insightful input. Too bad it’s unappreciated this time :frowning:

Before this turns into a flame war I’d like to state for the record that I’ve not said I dislike salathes comments. All I said was that in fairness it was a bit contradictory. Nothing more, nothing less.

The reason I complimented Joe was because it was straight forward encouraging advice.

Not really. Neither of the two programming styles you mention require buffering unless you have an error in your logic.

oddz mentioned one instance where you would legitimately use buffering - the use of buffering is only needed where you have that level of complexity in the overall system.

A beginner to PHP is a long way from even thinking about using the sort of constructs where buffering is required. Beginners are best off to forget that buffering even exists until they have gained a lot of experience of writing PHP without it since the sort of pages a beginner writes never need buffering if written correctly.

Those who use buffering by preference are potentially hiding lots of logic errors in their processing which could be easily found and fixed if they were not hiding them.

I was going to ask a similar question, then I saw this thread was on top. I am a beginner, and I am using a redirect after output, however, I am getting an error, as expected :). So here is the code (minfied to only include the necessary parts for this demo). Please point out the logic error.


<?php require_once('functions.php'); ?>
<!DOCTYPE HTML PUBIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<!-- head markup -->		
	</head>
	<body>
		<div id="header">
			<div>
			<?php
				if($foo == $bar){
					// do something
				}
				else{
					header('Location: index.php');					
				}
			?>
			</div>
.
.
.
.

Again, I’m a beginner, but the logic looks just fine to me. I pull in a functions file, and based on a simple if statement the page redirects.

I understand that php doesn’t want to redirect after it has already started output…but I don’t get why I have a logic error.

Well you would use ob_clean(); before setting the header. However, this is more less a terrible way to do things. However, there isn’t much you can do about it when programming procedurally. You headers must be set before sending any output. Therefore, using ob_clean(); will clear everything and you’ll be fine. Again… more or less a hack but it does the job.

I think I’m getting it… So is the point to program in such a way to just not output anything before redirecting if you know you’ll be redirecting?

Also, with ob_clean() on the line right above header(), I’m getting the same error, that output was already sent. Could there be something else I’m forgetting?

The logic error is that you’re doing things in the wrong order. You’re sending html before you actually determine whether or not you actually should send html. It’s like doing this:


echo 'top secret stuff';
if (!$user_is_logged_in) {
    // crap, we told them before
    // checking whether or not they are allowed to see it...
}


//proper logic
if ($user_is_logged_in) {
    echo 'top secret stuff';
}

But…the fact that output buffering is possible in php actually makes the first example proper logic(if you happen to be using output buffering). Proper logic or not, it’s generally considered poor design.

Regardless, it can be very convenient in certain cases. But be aware that your program flow and structure is off.

Thanks. I will keep this in mind as I learn php.

So, if I can’t get ob_clean() to work as suggested by oddz, is ob_start() and ob_end_flush() an alternative in this particular situation, considering the logic I’m using in a procedural style.

Better yet, does anyone have suggestions of how I could change what I’m doing as to not output anything before a redirect? Should I not mix html and php, but instead use more includes?

Includes aren’t really going to solve the problem. You really need to commit to structure supporting separation between display and application logic. Whether that is MVC or some other structure is up to you, but using includes will result in the same problem ultimately.


<?php require_once('functions.php');
if($foo != $bar) header('Location: index.php');
else {	
?>
<!DOCTYPE HTML PUBIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
	<head>
		<!-- head markup -->		
	</head>
	<body>
		<div id="header">
			<div>
			<?php
			// do something
			?>
			</div>
.
.
.
.
<?php } ?>

You may even be able to move the include into the else clause if there isn’t anything in there determining the values of foo and bar.

Just about all of the code where a redirect may sometimes be needed ought to follow this pattern. The logic error in doing it any other way is that you are producing output before you have decided iif you need it rather than deciding what to do and then doing it. Somewhat like jumping out of an aircraft and then asking yourself whether you ought to wear a parachute or not.

I have this situation where I will display an error message, then redirect user back to where they came from.

So in this case, there MUST be a output buffer right?

No because if you discard the buffer in order to do the redirect then your message doesn’t get displayed anyway and so you may as well not output the message if you are going to do the redirect.

Maybe the example I gave wasn’t clear.

Lets say if I want to output a message that the form submission was successful. And do a redirect to homepage after 5secs. This would be a case where output buffer MUST be available right?

I just want to be sure that output buffer is not a workaround, but is actually needed in some cases.

Not really.

The ideal way of doing that is to process the form before outputting anything. If the form submission is successful, display the correct relocation tags and, later on, a success message. Otherwise, don’t.

Absolutely NOT needed in that case since when you do that you can no longer do the redirect using PHP since the PHP finishes once the message is output.

Whether the redirect then runs or not depends on whether the person using the form has JavaScript or meta redirects enabled in their browser and which of those two you use to do the redirect. If you use both and they have both disabled in their browser then you leave them on the page with the message and no way to get to where they were supposed to be next - so you’d need an “if this page doesn’t redirect in 5 seconds” link in the output as well.

Buffering is only required for advanced applications where you have hundreds of different modules potentially outputting to the page. Unless you have a team of people working on the project the chances of your project being complex enough to require buffering is so close to zero as to be able to ignore that buffering exists.

1 Like

Bit of an exaggeration here.

I’ll often generate the body of an html page before generating the head of the page since the body might decide to add styles, scripts, etc to the head.

So I process the body template using output buffering then pass the results to the page template. Few lines of code. Very useful result.

You have completely changed topic to one where buffering is relevant.

This discussion has been about whether to generate ANY of the HTML page before using a header redirect and discarding the content of the buffer and there are few systems where that cannot be better done by first testing if you are going to create a page at all and redirecting before wasting time writing to the buffer. There is ALWAYS a minor change can be made to improve the logic to make buffering unnecessary in that situation.

What you are talking about is using the buffer to be able to generate the page content out of order. All of the content of the page from the doctype tag onwards is a part of that content and has nothing to do with the HTTP headers being discussed. Using the buffer to assemble the content out of order is what the buffer is there for.

Remember the web page gets sent in the following order:

  1. HTTP headers
  2. The head portion of the content
  3. The body portion of the content

Buffering allows you to generate parts 2 and 3 in whichever order makes most sense. It should not be used in order to avoid the minor code changes required to make sure that part 1 gets generated first.

1 Like

Hmmm.

You sure seem to be saying that buffering is always useless except for a tiny number of advanced applications. A newbie could easily misinterpret the above quote and give up a very powerful tool.

And while I try to isolate presentation from the application logic the fact is that there are millions of scripts out there that don’t. Yes it is a good thing to learn best practices but for many developers, using a global buffering scheme is the easiest way to solve this particular problem.