When to use ob_start() and ob_end_flush()

Should I use ob_start() at the beginning of every script that uses header(‘Location: file.php’) and ob_end_flush() at the end of that same script?

The necessity of using the output buffering functions depends on the individual script. The best practice, in general terms, is to separate processing code from code which issues output. Why would you want to send some output to the client and only later decide that it would be better to redirect them to another location — that in itself is a bad practice. Rather than wrapping up the code in output buffering (effectively putting a band aid over the problem) it’s generally better to re-organise the code so as to not require the output buffering remedy.

Several sources are telling me that, when redirecting to another page output buffering needs to be on. I’m asking when is the best position in the code to use ob_start() and ob_end_flush().

Please don’t believe those sources. There is absolutely no reason why output buffering needs to be used when redirecting.

If you want to play it safe and not really learn anything useful from making this thread then put ob_start() as high up your script as possible, and ob_end_flush() as far down as possible.

You have an attitude problem. Not learn anything? You’re giving me advice of exactly what you said not to do.

If you’re so concerned about me learning something you should have explained the points you want to get across.

Please don’t reply to anymore of my posts.

I wouldn’t agree with that particular point, just to clarify, but you’re absolutely entitled to read into my few words whatever notions you please.

By stating that you shouldn’t be doing what you want to do, I was aiming at guiding you along another train of thought; one which will be a far better practice for you to get into in the long run. You clearly were not interested in that so I gave you the simplest advice I could—what I thought you wanted to hear—even if it goes against what anyone else with any experience would say.

I was saving writing a few hundred words on why x is better than y and z (instead preferring a condensed approach at first) until such a time that it appeared you were receptive to reconsidering what you were asking. Why waste time going tangentially off-topic based on a one-line post?

Noted. It will not happen again unless directed to do so.

In fairness what you have said is a bit contradictory. You’ve told him not to use that method and then in the next reply told him to do just that!

I’m also in a similar situation… I use output buffering in the main script of my program as the main script handles several different things. Now… let me show you an example:

script-a.php is the main php script.

Now, it handles several things… It can output a form, a results page and finally redirect a user to another url. Now… how in advance is the script supposed to know if it should use output buffering or not?

I’ll appreciate that theoretically you could put all the scenarios in a switch() and then use output buffering in the appropriate case but if script-a.php also includes the use of a skin/template at the top… you’re stuffed because the headers have already been sent!

Get my drift?

For example, here is how my code works:


//script-a.php
include('header.php');

switch($_GET['mode'])
   {
   case "logon":
      //Log-on user and output page
      break;
   case "logoff":
      //Log-off user and output page
      break;
   default:
      //redirect..
      header('Location: other.html'); //ERROR!! - Headers already sent!
      break;
   }
include('footer.php');

Now, in that sample you’re stuffed so YES output buffering would need to be used at the top and bottom for every part of the program. I appreciate you can break the entire program up into seperate scripts but we all have different ways of coding!

It would make more sense, to me at least, to move things around a bit. Your scripts, in my opinion, would benefit from separating the decision-making logic from the behind-the-scenes actions and also the output. With your example code that might be structured something like:


// 1. Decide what this page wants to do
switch($_GET['mode'])
{
   case "logon":
   case "logoff":
   break;
   default:
      //redirect and stop further processing
      header('Location: other.html');
      exit;
   break;
}

// 2. Do it (super-basic example)
$view = $_GET['mode'](); // logon() or logoff()

// 3. Show pretty page
include('header.php');
echo $view;
include('footer.php');

With that sort of separation there’s no bother over the possibility of getting output before all of the necessary headers have been sent.

Off Topic:

With regards to being contradictory, I guess the last paragraph of that post (“If you want to play it safe…”) could have been prepended with “I wouldn’t advise doing this but”. I figured my view was already clear and didn’t need that kind of clause added.

I think Salathe has been the victim of misunderstandings here! His points are perfectly valid, and @OP, you need to sort your attitude out.

You’re posting on a forum where people give their own time to help others. To start off, you’ve been misinformed by people who (judging by what he said) spaghetti-codes and you shouldn’t really trust what he says, and Salathe simply pointed out that those sources shouldn’t be bothered with in a polite way and you reply by slating the guy who seems to make the most sense in this thread. You really need to think about that - the guy’s trying to help.

But basically, any code which affects the browser and the output of the page (e.g. could redirect the page, writes cookies, processes forms etc) should be done before anything at all is output - as Salathe pointed out.

The only place I would think about using output buffering is when wanting to store the output of an include in a variable, for example:

ob_start();
include('someView.php');
$something = ob_get_clean();

Using buffering and using redirects are two totally separate things. Your reasons for using buffering should not be dependent in any way on whether there are or are not any redirects within the code.

While buffering bypasses the error you get if you have output something to the page and then tried to do a redirect, it isn’t solving that problem, it is just hiding it. Buffering using ob_start() and ob_end_flush() are intended for a completely different purpose entirely.

You should use each command for the purpose for which it is intended. If you don’t know what buffering is really for then you shouldn’t be using it.

I do understand that and I do agree however sometimes due to the design logic of the code it’s not always possible to do things in a ‘perfect’ way and so you need to find a hack around it. I think it’s fair to say that regardless of whether buffering is used for its original purpose, if it gets the job done its good enough for most of us.

As above, it doesn’t really matter if it still achieves the desired results. I agree it’s not the perfect way of doing things but the end result in my case was the same - the browser was redirected. Point made!

I’ve never come across a situation where I have to output before I’ve done all the necessary processing (which may involve redirects).

I have! - Learners!

Learners should be encouraged gently and not told off, given a disciplining etc. Just gently explain where they’ve gone wrong and how it could be done better without contradiction. Code samples are always a winner with learners too instead of criticism no matter how mild it is.

I’m still a learner myself… but I’ve got a very good set of communication skills thanks to some tough jobs I’ve had in the past which needed me to talk my way out of some very hostile situations. I can break things up and explain them far better than some degree level programmers and all their hi-tech jargon talk. Sometimes experienced programmers without meaning to can sound offensive purely because they’re so good at what they do that they forget that new people don’t understand these so called ‘little’ issues and it can be intimidating to a new comer.

I’ve had my fair share of arguments with some of the best programmers known - including TeamB programmers. Took a while to work out it wasn’t them being narky, aggressive or rude, they just don’t have the same people skills that others do or they can’t break things down into simple terms to explain to learners. Remember learners are still practicing how to design their programs and logic processes. It’s something we’ve all had to do and we’ve all had to learn to re-design things.

Thats all it is.

I’m certainly not slating salathes response but it was a bit contradictory and from a learners POV confusing. As mentioned above some code samples or even logic samples would of worked wonders here.

Where you find that you have to redirect and you have already started to write output to the page you have a logic error in the way that your code is designed. It is fairly common for beginners who do not yet have much programming experience to have lots of logic errors in the code they are writing. You can’t expect them to gain all the necessary programming skills to do things perfectly in five minutes.

Where they have made a logic error and have asked more experienced programmers for help the correct solution is to explain how the code contains a logic error and how to rectify that particular error. Of course in order to do that you need to be able to see the actual code with the logic error in it in order to be able to explain exactly how to fix it.

As sd3923 hasn’t posted an example of their PHP code it isn’t possible to describe exactly how to fix whatever page it is that has the issues. All that can be said is that buffering just hides the logic error without fixing it and until you fix the logic error there is always the potential for there to be other problems caused by the logic error that the patch doesn’t hide. By all means post the actual code of any web page that contains a logic error like this so that more experienced programmers can assist you in fixing the logic error properly rather than just hiding it.

And this is about as best as you can put it.

Also maybe I’m wrong but it seems that php.net is often bypassed as a source to learn from

Off Topic:

[indent]Originally posted by Kayarc
Also maybe I’m wrong but it seems that php.net is often bypassed as a source to learn from[/indent]
The PHP manual available online at php.net (with offline versions available) is a very good technical document, and much effort is made to make it accessible to all levels of PHP developer (from introducing the absolute basic of the language, through to in-depth technical documentation) there do appear to be some hurdles in the path of beginners wanting to make use of it.

The various “book” sections go some way to helping, beyond the API documentation, but there is certainly still much scope for more teaching/tutorial style writing to encourage people to consider the manual as a place with information other than technical API docs. I’ve had a number of reports from people stating that the manual just goes way over their heads.

On that note, if you or anyone has any ideas, thoughts or requests then do feel free to contact me personally (my username at Sitepoint @php.net) or use the bug reporting system to make the team aware of any problems, oversights, issues, etc… :eye:

Output buffering is very useful when you would like to support nested controllers/modules. If a module/controller can be executed from within a template/view buffering is a must. The best place to use output buffering is when you would like to embed on template inside another and inside another and inside another and so on. Where the inner most template may execute a module/controller that would change headers, cookies, etc.

The below represents this simple scenario. Without output buffering ‘<p>master</p>’ would be sent to output and the nested module Login would not be able to affect the state of cookies, headers, etc w/o error.


<p>master</p>

<?php echo $this->_objDriver->executeModule('Login'); ?>

I’d also agree with that. I’m only a learner and I’m there on a daily basis but its frightening how many folks come here to ask even the most basic questions! Questions which are easily solved, understood and learned from by visiting php.net.

My biggest trouble is remembering what parameters functions take and in what order… hence I’m a pretty regular visitor.

Simple answer, no. Not every script.

If it’s an existing script that you’re modifying, you’ll have to determine how that script works and see if there will ever be a case when either your additions will use the header function after the existing script has printed/echoed something, or if your addition will print/echo something before the existing script uses the header function.

If the answer is yes to either situation, using ob_start() is a fix. Just like putting a plug in a flat tire is a fix. It works, it will work until you can get a new tire, but it’s not as good as having the new tire. There’s also the chance that it’s a tear in the tire that could be mended back together using industrial adhesive, which again is a fix, but still not as good as a new tire.

If it’s a new script you’re writing, then it’s a matter of preference. Some people like to mix PHP and HTML like the following here.

<div><?php echo $something; ?></div>

It’s not “wrong” per-say, but that style of coding sometimes forces you to use output buffering (what’s actually provided by ob_start) if there is any chance of needing to send any HTTP Headers (not just “Location:”) with the header() function later in the application.

So if you’re using that style of mixed PHP/HTML, then yes. You should probably use ob_start() at the beginning of “every script that uses header('Location…” like you asked. I stress probably though, because it could be argued that you should be able to determine whether any headers will be sent before outputting anything. In which case you wouldn’t need to use the buffer.

If you’re not the type to use the mixed PHP/HTML style, and your code generally looks more like the following

<?php
$template = new template('./html401.html');
$template->load_file_into('./cache/popular.html', '<div id="popular"/>');
echo $template;
?>

Then chances are you’re not going to need output buffering much, if at all. The application will generally have its’ own output buffering logic built in, and have no need for the PHP output buffer.

There are exceptions, occasionally you’ll come across strange functions or code bases you’re forced to work with that echo/print from within a function instead of returning the value. Sometimes you have to wrap that section up using the output buffering functions, but it’s not going to require you to use ob_start at the beginning of every script.

The only way that I can see a use for it is if you want to a meta refreh type redirect. you could echo out “Redirecting to …” sleep, then header location.

Other than that it makes no sense to start output if you are doing a header location redirect.

My 2c