In order to understand the value of the statements you have written you need to have some basic understanding of the operations of the functions you mention. I'll try to break them down here.
Let's start with session_start()
and header()
calls:
The first function does exactly what the name implies; it starts a session.
Due to the stateless nature of the HTTP protocol, there is a need for some mechanism that can remember state between page requests. This can be achieved with sessions. Although sessions, in the early days of PHP where sometimes propagated by passing along the session ID in links ( someurl?sessionId=someSessionHash
), this, nowadays, is considered bad practice.
Nowadays, sessions are predominantly kept track of by using a cookie (in the early days they where widely used too, don't get me wrong). This session cookie (which, contrary to popular belief, is nothing more than a normal cookie, with merely the session ID in it, that (usualy) simply expires after you close your browser) is sent along to the browser with each subsequent page request. And here is where the catch is: A cookie is sent as a header of the response (meaning before the actual body), like so:
// I've left out a lot of other headers for brevity
HTTP/1.x 200 OK
Date: Sun, 31 Jan 2010 09:37:35 GMT
Cookie: SESSION=DRwHHwAAACpes38Ql6LlhGr2t70df // here is your Cookie header
// after all response headers come the actual content:
// the response body, for instance:
<html>
<head>
</head>
<body>
</body>
</html>
Now, because response headers must be sent before the response body, you need to put a call to session_start()
and header()
before any body content is output. Here's why: if you output any response body content (could be something as simple as a whitespace character) before a call to session_start()
or header()
, PHP will automatically output the response headers. This is because a HTTP response must have the response headers sent out first before the response body. And it is exactly this that often leads to the infamous Warning: headers already sent
warning in PHP. In other words; once PHP has sent out the headers, because it had to send body data too, it cannot add any headers anymore.
So, now that you understand this about the HTTP protocol, there are some measurements you can take to prevent this from happening. And this is where we come to the next function(s):
ob_start
, ob_flush
, etc...:
In a default setup PHP usualy outputs anything immediately. Therefor, if you output any response body content, headers are automatically sent first.
But PHP offers mechanisms of buffering output. This is the ob_*
family of functions. With ob_start
you tell PHP to start buffering. And with ob_flush
you tell PHP to flush the buffer; in other words output the current content of the buffer to the standard output.
With these buffering mechanisms you can still add headers to the response, after you have output body data, because you haven't actually sent body data yet, you have simply buffered it, to be output later with a call to ob_flush
or ob_end_flush
and what have you.
Keep in mind though, that using ob_*
functions is more than often a code smell. In other words (and this is why it is important to do certain stuff at the top), it is then used to make up for poor design. Somebody forgot to set up their order of operations properly and resorts to output buffering to circumvent this header
and session
drama.
Having said all this, you can easily see why the outputting of html and/or other body content should come last. Apart from that, I strongly recommend you to separate PHP code from output code anyway. Because it is much more easy to read and understand. And a good way to start doing that is having the actual html come after the main <?php ?>
code block. But there are other ways as well, which is beyond this questions scope.
Then lastly about the include
and require
calls. To have these at the top of your php files is usually ment to be clarifying. It keeps these calls nicely in one place. But keep in mind, that if one of these files output anything before you call session_start()
or header()
without using output buffering, you're screwed again.