Warning: Cannot add header information - headers already sent by (output started at file.php:23)
Have you ever gotten that warning message in PHP? Wonder what it's all about? Well, we can cover this very easily.
You are trying to send header information AFTER you have sent output to the browser.
Okay, lets give you an example of what will give that error.
<?php echo "hello"; header("Location: http://www.phpcomplete.com");?>
This will raise an error, because you outputted hello to the browser via echo BEFORE you used the header() function. The header() function sends header information to the browser, so it makes sense the header inforation would come BEFORE the body, or the actual document. As soon as you send ANY content or data to the browser that isn't header information, you can't go back and send header information.
This would also give you an warning:
<?php header("Location: http://www.phpcomplete.com");?>
While it may seem like the above isn't sending any data other than header information, the problem is in the spaces BEFORE the opening PHP tag. That is a problem, because that is actual data.
People seem to get confused most often with header() because they think they can do something like this:
formTest.php
<?php
// Form has been submitted...
if ( isset($_POST['submit']) ) {
if ( empty($_POST['emailAddress'])) {
echo "You didn't fill in your email address.";
header("Location: formTest.php");
} else {
echo "Email was filled in.";
header("Location: emailOkay.php");
}
}
?>
<form method="post" action="formTest.php">
Enter an Email: <input type="text" name="emailAddress" />
<input type="submit" name="submit" value="Submit Email Address" />
</form>
emailOkay.php
This seems to be a common problem amongst newbies. For some reason, they think that they can output data to the browser, and then send header information. Unfortunately, they are confusing the HTML meta-refresh tag with the PHP header() function.
The above can be rewritten as such:
formTest.php
<?php
// Form has been submitted...
if ( isset($_POST['submit']) ) {
if ( empty($_POST['emailAddress']) {
header("Location: emailOkay.php");
} else {
echo 'Email was not entered.';
}
}?>
<form method="post" action="formTest.php">
Enter an Email: <input type="text" name="emailAddress" />
<input type="submit" name="submit" value="Submit Email Address" />
</form>
emailOkay.php
The above example displays how easy it is to redirect using the header() function along with forms.
Another problem newbies face with the header() function is the infamous error that occurs in weird places that aren't echo'ed out, for example:
examplePage.php
<?php
include "databaseInit.php";
// some normal non-display code here
header("Location: nextStep.php");
?>
databaseInit.php
<?php
mysql_connect('localhost', 'username', 'password');
mysql_select_db('database');
?>
Here, the problem is in databaseInit.php, and it has to do with the blank lines. The blank lines before the code starts, and after the code end - both will cause problems. Remember, NO output whatsover, blank lines included!
Now, you may be feeling like that is a lot of work to use header(), but their is an easy solution to all of this: output buffering.
Output buffering is not only easy to use, but it works miracles. All the above examples could use output buffering, and would NOT cause errors, and would basically work. So you probably want to know how to use output buffering, so I will tell you.
In the above example with the database connections, we could do something like this:
examplePage.php
<?php
include "databaseInit.php";
// some normal non-display code here
echo "Stuff happens here";
header("Location: nextStep.php");
// other code for other things...
include 'cleanUpModule.php';
?>
databaseInit.php
<?php
ob_start() // turn output buffering on
mysql_connect('localhost', 'username', 'password');
mysql_select_db('database');
?>
cleanUpModule.php
Note: I never tried it, but I am told ob_end_flush() is called implicitly at the end of the PHP script, so you wouldn't even need to call ob_end_flush() at the end here if that is true.
Anyways, basically, output buffering doesn't send anything out to the browser until you tell it to, so you can have ouput and headers in whatever order you want. This is useful for many reasons, but even more useful in large projects when you don't know if someone is output something. The above would work, reordering the echo to happen after the header() function (of course, echo would never run, because header() would change the page location).
Well, that's it, I hope this clears up some problems. On a short note, everything here also applies to sessions and working with cookies. Once you send output, you can set a session or change cookies values. The methods here apply in the same manner though.
Enjoy =)