Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 1 of 1
  1. #1
    Senior Coder
    Join Date
    Feb 2011
    Location
    Your Monitor
    Posts
    4,309
    Thanks
    58
    Thanked 525 Times in 512 Posts
    Blog Entries
    5

    TIP: Warning: Cannot modify header information - headers already sent

    I thought this would be a useful thread as it seems to be a common error that a lot of new coders don't quite understand.

    Many new php coders see this message and will not understand it. In order to understand what PHP is telling us we need to understand how the HTTP process works.

    This is a basic web page HTML source code:
    Code:
    <html>
       <head>
          <title>Hello World</title>
       </head>
       
       <body>
       This is a basic HTML page.
       </body>
    </html>
    With any web page that you request, your browser (Internet Explorer, Firefox, Opera, SeaMonkey, Safari etc) sends the request as a series of lines of text called request headers. The server will then locate the file, pass it to PHP if needed and then it is ready to send it to you.

    When the server sends you this information it sends some information first called reply headers similar to the request headers. These headers are basically text information which the browser does not display but uses internally. After the headers, the server sends a blank line which the browser then understands as the end of the headers. After this blank line is the HTML source for the page.

    So what are request and reply headers?
    Well for the request they contain many things such as the language the browser accepts, the Browser type, the requested page and sometimes other things. For the reply they contain things such as the content length (so that little blue bar knows when the page is 100% downloaded), the http status code, the server software,the content type, the date and time and some others. You'll see an example further down.

    So to recap, a http request and response works like this:
    Code:
    <Request Headers>
    
    <Reply Headers>
    
    <HTML>
    At this point, I would like to make one thing very clear:
    Reply Headers can only be sent ONCE.
    This is because the browser has no way of knowing where the html ends (your html may contain many blank lines and the closing </html> tag may also have more content after it).

    To understand this better, here is a sample from a http program I have which displays raw output from a server:
    Code:
    Connected.
    Sent: GET /HW.php HTTP/1.0
    Sent: Host: localhost<EOL>
    Sent: Accept: text/html, */*
    Sent: User-Agent: Mozilla/3.0 (compatible; Indy Library)
    Sent: 
    Recv: HTTP/1.1 200 OK
    Date: Sat, 18 Jun 2011 19:11:10 GMT
    Server: Apache/2.2.17 (Win32) mod_ssl/2.2.17 OpenSSL/1.0.0d PHP/5.3.6 DAV/2
    X-Powered-By: PHP/5.3.6
    Vary: User-Agent,Accept-Encoding
    Content-Length: 131
    Connection: close
    Content-Type: text/html
    X-Pad: avoid browser bug
    
    <html>
       <head>
          <title>Hello World</title>
       </head>
    
       <body>
       This is a basic HTML page.
       </body>
    </html>
    Cookies and Sessions (Sessions are also reliant on Cookies frequently) are set inside the reply headers.

    To understand how a cookie or session is set, here is an example of the particular header responsible for it which you would see in the reply header:
    Code:
    Set-Cookie: PHPSESSID=f6kr15gbblr29hjjqa7r6s8ll2; path=/
    At this point I should also point out that sometimes you may wish to use the header() function to perform a redirect. The header() function also uses the reply headers to perform its task. When using header('Location: something.html') you would see a header like this:
    Code:
    Location: something.html
    Now lets suppose we have the following code:
    PHP Code:
    <?
    $Title 
    'Hello World';
    $Content 'This is a basic HTML page.';
    ?>

    <html> <!-- This line triggers reply headers (HTML output)-->
       <head>
          <title><? print $Title?></title>
       </head>
       
       <body>
       <? print $Content?>
       </body>
    </html>

    <?
    //This will not work - HTML output has already triggered the reply headers.
    setcookie('Demo''Cookie');
    //Also sends a cookie
    session_start(); 
    ?>
    With the code above you will see the following message:
    Cannot modify header information - headers already sent
    This is because when your script started, it output the <html> tag which is the start of the output process. This output caused the server to send its reply headers which as stated above can not be altered or resent. Output can be either static HTML and/or PHP via the print / echo commands.

    IMPORTANT NOTE: Output can also be whitespace or a carriage return (End Of Line) character. If you have source code which has either at the beginning of your script this will cause your reply headers to be sent. Here is a sample:
    Code:
    
       <!--There is whitespace above and before this comment-->
    <?
    $Title = 'Hello World';
    $Content = 'This is a basic HTML page.';
    ?>
    
    <html>
       <head>
    So how do we deal with this?

    There are 2 main ways to avoid this situation:

    1) Restructure your code:
    • Output headers before HTML - This includes session_start(), setcookie() & header()
    • Seperate your PHP and HTML
      • Process your PHP, set headers, merge variables into templates then print.

    2) Use output buffering.

    Item 1 can be rather complex and open to debate. The main principle however is that you run any code which triggers a header to be sent BEFORE you print any html. This can actually help you to become a better coder especially if you process all your php first and then merge any variables into a template before printing.

    Why?
    Well thats simple. If you process your php first, you can use session_start(), setcookie() or header() anywhere within your PHP before sending your html output to the clients browser. Additionally it helps you to write clearer code which is easier to understand and modify in the future.

    Here is an example of Item 1:
    PHP Code:
    <?
    $Title 
    'Hello World';
    $Content 'This is a basic HTML page.';
    //Do some other PHP only stuff here:
    for ($I 0$I 100$I++)
       {
       
    $J I;
       }
       
    session_start();

    $HTML "
    <html>
       <head>
          <title>$Title</title>
       </head>
       
       <body>
       $Content
       </body>
    </html>"
    ;

    //Modify headers - This WILL work
    setcookie('Demo''Cookie');

    //Now we can output our content - at the end.
    print $HTML;
    ?>
    Item 2:
    Sometimes however, after you've spent days working on your code it isn't practical to rework all of your code. Fear not my friends, this is where output buffering comes to your rescue.

    What is output buffering then?
    Output buffering is simply a method PHP uses internally to catch and store all output from your script into its own memory. When output buffering is used, PHP does not pass anything to the server which would trigger the reply headers to be sent. Your script can run as normal, storing output into the output buffer, process php code, perform calculations, database queries, set cookies, start sessions etc and then finally flush the buffer (HTML output) to the browser. This means that using functions such as setcookie() or start_session() will work because the headers have not been sent and thus can be modified internally by PHP and the web server.

    Here is an example of the original code (which failed) using output buffering:
    PHP Code:
    <?
    //Turn on output buffering
    ob_start();

    $Title 'Hello World';
    $Content 'This is a basic HTML page.';
    ?>

    <html>
       <head>
          <title><? print $Title?></title>
       </head>
       
       <body>
       <? print $Content?>
       </body>
    </html>

    <?
    //This will not work - HTML output has already triggered the reply headers.
    setcookie('Demo''Cookie');
    //Using sessions also sends a cookie
    session_start(); 

    //Turn off output buffering:
    ob_end_flush();
    ?>
    As you can see, output buffering started and ended at the beginning and end of the code. This means that everything in between was temporarily stored in PHPs output buffer allowing you to set a cookie and use sessions before finally turning off the output buffer and flushing it out (printing it) to the clients browser.

    I hope that this will help you in your future PHP programming.
    Last edited by tangoforce; 06-19-2011 at 06:46 PM.
    See my new CodingForums Blog: http://www.codingforums.com/blogs/tangoforce/

    Many useful explanations and tips including: Cannot modify headers - already sent, The IE if (isset($_POST['submit'])) bug explained, unexpected T_CONSTANT_ENCAPSED_STRING, debugging tips and much more!

  2. Users who have thanked tangoforce for this post:

    low tech (06-20-2011)


 

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •