Warning: Cannot add header information

Tutorials on PHP, databases and other aspects of web development. Before posting a question, check in here to see whether there's a tutorial that covers your problem.

Moderator: General Moderators

jason
Site Admin
Posts: 1767
Joined: Thu Apr 18, 2002 3:14 pm
Location: Montreal, CA
Contact:

Warning: Cannot add header information

Post by jason »

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.

[syntax="php]<?php echo "hello"; header("Location: http://www.phpcomplete.com");?>[/syntax]

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:

Code: Select all

  <?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

Code: Select all

<?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

Code: Select all

Your email was okay.
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

Code: Select all

<?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

Code: Select all

Your email was okay.
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

Code: Select all

<?php
include "databaseInit.php";
// some normal non-display code here
header("Location: nextStep.php");
?> 
databaseInit.php

Code: Select all

 

<?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

Code: Select all

<?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

Code: Select all

<?php
ob_start() // turn output buffering on
mysql_connect('localhost', 'username', 'password');
mysql_select_db('database');
?> 
cleanUpModule.php

Code: Select all

<?php
ob_end_flush();
?>
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 =)
Last edited by jason on Sun Sep 21, 2003 7:32 pm, edited 1 time in total.
User avatar
Crashin
Forum Contributor
Posts: 223
Joined: Mon May 06, 2002 3:42 pm
Location: Colorado

Post by Crashin »

Thanks for that post! That must've taken a while to put together...
User avatar
Kriek
Forum Contributor
Posts: 238
Joined: Wed May 29, 2002 3:46 am
Location: Florida
Contact:

Post by Kriek »

So Jason am I doing this right?

Code: Select all

 
<? 
if($id=="3") echo("<!-- Page validated -->"); 
else header("Location: Page.php?id=3"); 
?>
 
I'm not having any problems with this, but that doesn't mean it's proper =)
Last edited by Benjamin on Mon May 11, 2009 2:05 am, edited 1 time in total.
Reason: Added [code=php] tags.
qads
DevNet Resident
Posts: 1199
Joined: Tue Apr 23, 2002 10:02 am
Location: Brisbane

Post by qads »

if there is't anything else before this code then it is fine.
NNParksITGuy
Forum Newbie
Posts: 4
Joined: Sat Oct 26, 2002 6:39 pm
Location: Newport News Virginia

that's the ticket

Post by NNParksITGuy »

Some of this I knew, but didn't know WHY. It's always in the details, isn't it?

Thanks for a well written mini-how-to!
User avatar
Kriek
Forum Contributor
Posts: 238
Joined: Wed May 29, 2002 3:46 am
Location: Florida
Contact:

Post by Kriek »

ob_start() and ob_end_flush() saved my life! :D
User avatar
harsha
Forum Contributor
Posts: 103
Joined: Thu Jul 11, 2002 1:35 am
Location: Bengaluru (Bangalore) > Karnataka > India

if there is cache problem

Post by harsha »

is it prefered
use switch statement to navigate it is more clear.
what i heard was this
" it make the code split easily and we can edit the code with out complication and prevents using header(Cache-control:)..
and other thing like that and it needs only few <meta tags> to refresh."
mclarko
Forum Newbie
Posts: 3
Joined: Tue Dec 10, 2002 5:08 am

A workaround

Post by mclarko »

Not knowing whether stuff echoed to browser, I've used a js workaround. If it's flawed, then grill me by all means! ;-)

Code: Select all

<script type="text/javascript"> 
<!--
location='display.php?record_id=<?php echo "$record_id"; ?> ';
// -->
</script>
 
Last edited by Benjamin on Mon May 11, 2009 2:07 am, edited 1 time in total.
Reason: Added [code=javascript] tags. Updated code to reflect current best practices.
laserlight
Forum Commoner
Posts: 28
Joined: Wed Jan 01, 2003 6:41 am

Post by laserlight »

actually I first got such an error message when using cookies.

the entry on cookies in the php manual included a something on it happening for header() though, so that was sort of killing 2 birds with 1 stone :)
User avatar
Pamela
Forum Newbie
Posts: 3
Joined: Mon Jan 13, 2003 7:29 am
Location: Fairbanks, Alaska

Post by Pamela »

I really want to learn PHP. I tried the example in the first post

Code: Select all

<?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>


and I got an error message:
Parse error: parse error in .../php/phptestform.php on line 4
http://pamelajoy.com/php/
Last edited by Benjamin on Mon May 11, 2009 2:08 am, edited 1 time in total.
Reason: Changed [quote] to [code=php]
User avatar
Elmseeker
Forum Contributor
Posts: 132
Joined: Sun Dec 22, 2002 5:48 am
Location: Worcester, MA

Post by Elmseeker »

You are missing a ) it should be:

Code: Select all

if ( empty($_POST['emailAddress']) ){ 
 
User avatar
moniarde
Forum Newbie
Posts: 20
Joined: Thu Feb 06, 2003 12:45 am
Location: Perth, Western Australia

ob_start in relation to cookies

Post by moniarde »

I've noticed that this phenomenon also occurs with setcookie. Everytime I want to get around it, I find that ob_start works just as well.
For instance, this won't work.

Code: Select all

<html>
<body>
<?php
 
echo "testing 1,2,...";
setcookie("testcookie", "test");
 
?>
</body>
</html>
But this will.

Code: Select all

 
<?php
ob_start();
?>
<html>
<body>
<?php
 
echo "testing 1,2,...";
setcookie("testcookie", "test");
 
?>
</body>
</html>
Hope that helps. :D
hawk
Forum Newbie
Posts: 3
Joined: Thu Mar 20, 2003 6:58 am
Contact:

Post by hawk »

Here is a function that can be used for redirecting when you don't want to use output buffering

Code: Select all

function JSRedirect($url){
 print "<html><script>
   document.location='$url';
  </script></html>";
}
Last edited by Benjamin on Mon May 11, 2009 2:09 am, edited 1 time in total.
Reason: Changed [code] to [code=php]
User avatar
Wayne Herbert
Forum Commoner
Posts: 34
Joined: Tue Apr 29, 2003 3:13 pm
Location: Houston, Texas

Holy H Moly!!!

Post by Wayne Herbert »

I've been fighting an image display problem out of a database for a week... yes... I am doing basic research... I have no idea what I am doing.

These header tips... watching out for blank lines that force a header and using buffered output worked like a charm.

I can start replanting all the hair I pulled out this week.

Many thanks to those of you who take the time to teach.
User avatar
wmasterj
Forum Commoner
Posts: 40
Joined: Mon Aug 18, 2003 5:52 pm
Location: Stockholm, Sweden

Post by wmasterj »

i don't know why but that ob_*() stuff has never worked for me!

oh well!
Post Reply