A common problem found by starting PHP programmers is the warning:

Warning: Cannot modify header information – headers already sent by (output started at index.php:1) in index.php on line 3

Before understanding this problem, you have to know how pages are transmitted using the HTTP-protocol.  Any page or image you receive looks like this:

HTTP/1.x 200 OK
Date: Thu, 07 Aug 2008 10:46:41 GMT
Server: Apache/1.3.41 (Unix)
Keep-Alive: timeout=5, max=500
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8

<html> ...

The upper half of the content are the page headers. These are used by the browser to identify the page, but are also used to set cookies. The other half is the content of the page. When you have sent any content to the browser, you can’t change the headers anymore.

This is exactly where the error comes from. If you want to change the headers of a file, there may not have been any output to the browser. Even a space or new line is output!

There are three common PHP-functions that cause this error. Obvious is the header()-function, but also setcookie() and session_start() will change the header information (the latter depends on your configuration, see also my post about sessions).

The best solution for the error is preventing any output before you set any headers. You should put all your source code before you output anything, including whitespace. So your page should be like this:

<?php
  some php code which may change headers
?>
<html ...

If you, for whatever reason, fail to start your page with <?php, there are some possible things you can do:

  • First, if you scripted correctly, try to check the source of your page at the editor of your webhost. For whatever reason, sometimes uploading the page, or using another character set, causes the page to be changed and for example, some garbled text being added before the <?php-tag;
  • If you are still sure that you don’t have any output before the <?php-tag, you could try to use ob_clean();
  • You can let your script start with ob_start(). This will buffer any output till you call ob_end_flush() (at the end of the page). If you use this, you are able to place the three functions anywhere in your source;
  • If the problem is caused by session_start(), you can try to set session.auto_start on. How this can be done, please refer to my post about sessions.

However, you should try to fix the problems without functions of the Output Buffer or session.auto_start, to make your script more reliable.