-1

I know this question has been posted many times before, but I've been unable to find a good answer anyway, since the error doesn't exactly behave as it should.

You see, I have code similar to this:

<?php
    include("banner.php");
    include("menu.php");
    print "<div class=\"wrapper\">";
        if(true) header("Location:index.php");
        else print "Hello World";
    print "</div>";
    include("footer.php");
?>

banner.php looks like this:

<div id=banner><a href=index.php><img src=img/banner.png></a></div>

and menu.php looks like this:

<ul class="menu">
    <li class="dropdown">Menu
        <ul>
            <a href="test1.php?id=<?php print $id; ?>"><li>Item 1</li></a>
            <a href="test2.php?"><li>Item </li></a>
            <a href="test3.php"><li>Item 3</li></a>
            <a href="test4.php?id=<?php print $id; ?>"><li>Item 4</li></a>
        </ul>
    </li>
</ul>

Note that there are a few PHP elements in menu.php.

If I run the first piece of code, I get the error Warning: Cannot modify header information - headers already sent by (output started at /var/www/menu.php:10) in /var/www/test.php on line 5. Line 10 in menu.php is the last line. If I remove the menu completely from the code, and leave banner.php, the code works fine. I find this confusing, since banner.php does too provide output, as does the print "<div class=\"wrapper\">"; line right after the inclusion of the menu.

My question is simply this: Why does menu.php trigger the error, while banner.php doesn't?

EscalatedQuickly
  • 400
  • 4
  • 22

3 Answers3

1

This would happen if the output is being buffered, and the last line of menu.php filled up the buffer and flushed it down the wire.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • This seems reasonable, and in my `php.ini` I have `output_buffering=4096`, so it does seem likely. Thank you! And thank you, @Mr.Alien, for the tip! – EscalatedQuickly Jul 21 '13 at 11:57
0

Any PHP that modifies a header need to be before any other page data, unless you have output buffering on. The header gets sent right when you output ANYTHING. HTML code, PHP, ect..

Think of the PHP code as a facet, and the web server is a glass. Lets imagine that we're going to fill up the glass with the output of the HTML. As soon as it gets the first drop the headers are already established for what it's going to send.

You can turn on output buffering in your PHP.ini.

Output buffering basically like a measuring cup where you have the PHP code fill the measuring cup and when it gets to a certain point it gets poured into the glass cup (Web server). While it's being built up, it's still in PHP we have access to it which is why we're able to modify the headers we haven't given anything to the web server. However, take note that this has a performance impact on the server. You probably won't notice it though.

ECMAScript
  • 4,439
  • 4
  • 21
  • 29
0

HTTPHeader must be the first thing to send. And any output from the script (even if it is a single character or error message) is proceeded by HTTP Headers. and once the content send is started additional header cannot be sent. This is HTTP Protocol basics. I will explain it WRT your code.

<?php
    include("banner.php");
    //The above line the banner output is sent.So does the HTTP Headers
    include("menu.php");
    print "<div class=\"wrapper\">";
        if(true) header("Location:index.php");
        //Because the Output is started in bannrd you cannot send additional headers.
        else print "Hello World";
    print "</div>";
    include("footer.php");
?>

If you have output buffering turned on in php.ini then unpredictable results can happen, as headers are never buffered and the content is only buffered. In your case it looks like you send the header before php flushes the banner code.

bansi
  • 55,591
  • 6
  • 41
  • 52