If you’ve ever modified header information in PHP, you’ve probably already seen this error. The first time you see it, it is often difficult to understand what the error means and what could cause such an error.
First, let’s have a look at what the error means. Whenever your PHP script returns some HTML code, first a header is sent which contains some metadata about the server, caching behavior, cookies, the following content… This header can also be used to redirect the user to a different URL.
You can check the header returned by a URL using this tool.
Once the header has been sent to the client, you cannot modify it anymore. Additionally, once you’ve started sending some contents, the header will have been implicitly sent. So after sending the header whether implicitly or explicitly, you should not try to modify the header anymore.
Modifying the headers
Second let’s see how you can modify the headers using PHP. There are three main functions which modify the headers:
So you should not output ANY content before calling any of these functions.
Third let’s see how you could ouput some content either knowingly or by mistake.
The obvious way to output some content is using the echo function. So the following will lead to this error:
<?php echo "some contents" header('xxx: yyy'); ?>
This one is pretty easy to identify. There are two solutions:
- Get rid of the echo before the call to the header function
- Use ob_start() and ob_flush()
Characters before before <?php
Everything which is not between <? and ?> will be considered to be content. So if you have anything before <?php header('xxx: yyy'); ?>
Or a newline:
<?php header('xxx: yyy'); ?>
Or a Byte-Order-Mark (aka BOM). For more information regarding the BOM and how to remove it, please check this article.
The solution in all these cases is to get rid of everything before <?php.
HTML before PHP code
Similar to the previous issue, you could also have HTML code on purpose before your PHP code e.g.:
<html> <body <?php ... header('Location: http://...'); ... ?> </body> </html>
If you mix HTML and PHP, you should never call header, setcookie or session_start in the php code found after some HTML code. If you need to call any of these functions, you should use ob_start() and ob_flush() and output the whole HTML content from you PHP code.
Characters after before ?>
Similar to the problem with characters before before <?php, if you include a PHP script in another and the included PHP script contains some characters after ?>, you will be in trouble. This is because those characters will be considered content and output before the rest of the code in the including PHP file.
The solution is again the same: remove all empty lines and white spaces after ?>.
One solution mentioned above is to use ob_start() and ob_flush() to buffer output. This means that all content output after the call to ob_start() will be buffered and only sent when you call ob_flush().
Here’s a short example:
<?php ob_start(); ?> <h1>My heading</h1> <?php session_start(); ob_flush(); ... ?>
In this example, the H1 tag will not be output until ob_flush() is called, so after the call to session_start().
There is also another function called ob_end_flush(). The difference is that ob_flush flushes the contents of the buffer but keeps the buffer alive, so content after ob_flush() will also be buffered. When you call ob_end_flush(), you flush the buffer and destroy it (i.e. turn off output buffering). So you’d use ob_flush() to already send some content to the client, while further producing additional content. And you use ob_end_flush() once the whole content has been added to the buffer.