85

I've been struggling with this error for a while now.

To start with, I just thought it was white space, but after further research I think it might be a problem similar to this:

Look for any statements that could send output to the user before this header statement. If you find one or more, change your code to move the header statement before them. Complex conditional statements may complicate the issue, but they may also help solve the problem. Consider a conditional expression at the top of the PHP script that determines the header value as early as possible and sets it there.

I'm guessing the include header is causing the problem along with the header(), but I'm not sure how to rearrange the code to get rid of this error.

How do I remove the error?

<?php
    $username = $password = $token = $fName = "";

    include_once 'header.php';

    if (isset($_POST['username']) && isset($_POST['password']))
        $username = sanitizeString($_POST['username']);

    $password = sanitizeString($_POST['password']); //Set temporary username and password variables
    $token    = md5("$password"); //Encrypt temporary password

    if ($username != 'admin')
    {
        header("Location:summary.php");
    }
    elseif($username == 'admin')
    {
        header("Location:admin.php");
    }
    elseif($username == '')
    {
        header("Location:index.php");
    }
    else
        die ("<body><div class='container'><p class='error'>Invalid username or password.</p></div></body>");

    if ($username == "" || $token == "")
    {
        echo "<body><div class='container'><p class='error'>Please enter your username and password</p></div></body>";
    }
    else
    {
        $query = "SELECT * FROM members WHERE username='$username'AND password = '$token'"; //Look in table for username entered
        $result = mysql_query($query);
        if (!$result)
            die ("Database access failed: " . mysql_error());
        elseif (mysql_num_rows($result) > 0)
        {
            $row = mysql_fetch_row($result);
            $_SESSION['username'] = $username; //Set session variables
            $_SESSION['password'] = $token;

            $fName = $row[0];
        }
    }
?>
Community
  • 1
  • 1
Rob
  • 1,479
  • 5
  • 18
  • 24
  • 1
    What does `header.php` look like? – jeroen Mar 14 '12 at 18:18
  • 2
    Place `include_once 'header.php';` after the `if ($username...` if/else chain so the redirection headers are not called after the HTML header is output. – Michael Berkowski Mar 14 '12 at 18:18
  • 3
    Assuming that there are no spaces before the in the file you listed, there's some output occurring in the header.php file, intended or not. If header.php is actually supposed to produce some output, then you should place the login conditional before you include header.php, otherwise you'll just need to go in and eliminate any output created in the header.php file. Most likely culprits, in my experience, is extra whitespace either before the opening tag or after the closing ?> tag. For certain if you don't see any characters before the error, you're looking for whitespace. – Jason Mar 14 '12 at 18:37
  • Thanks for the replies. I moved the include header below the headers() and I'm not getting the errors. However, the header file includes the menu options for each location so as I've moved the include header below the headers() the menu options are not changing. – Rob Mar 14 '12 at 18:57
  • 1
    http://stackoverflow.com/search?q=headers+already+sent – PeeHaa Mar 14 '12 at 20:31
  • ~~~~~~~~~~ file ENCODING should not be `UTF-8`, but `UTF-8 (Without BOM)`~~~~~~~~~~~ – T.Todua Sep 19 '14 at 08:02

4 Answers4

240

The long-term answer is that all output from your PHP scripts should be buffered in variables. This includes headers and body output. Then at the end of your scripts do any output you need.

The very quick fix for your problem will be to add

ob_start();

as the very first thing in your script, if you only need it in this one script. If you need it in all your scripts add it as the very first thing in your header.php file.

This turns on PHP's output buffering feature. In PHP when you output something (do an echo or print) it has to send the HTTP headers at that time. If you turn on output buffering you can output in the script but PHP doesn't have to send the headers until the buffer is flushed. If you turn it on and don't turn it off PHP will automatically flush everything in the buffer after the script finishes running. There really is no harm in just turning it on in almost all cases and could give you a small performance increase under some configurations.

If you have access to change your php.ini configuration file you can find and change or add the following

output_buffering = On

This will turn output buffering out without the need to call ob_start().

To find out more about output buffering check out http://php.net/manual/en/book.outcontrol.php

SamHennessy
  • 4,288
  • 2
  • 18
  • 17
  • @SamHennesy where do i have to add ob_start() under the header or at the start of the page? – Sharif Aug 20 '14 at 16:44
  • 1
    @Sharif , have it as early as possible. If that's the start of the page then that. The majority of the time there is no harm in calling ob_start(). – SamHennessy Aug 20 '14 at 21:14
  • Is this good practise? I mean since `PHP` is throwing an error does that mean there could be a better way of doing it. – James111 Jul 18 '15 at 10:43
  • @James111, this is often an issue when trying to add tests to a legacy application. Often the application was not designed to be run from the command line. Ideally you refactor the application to support run like this. Ideally if you are going to refactor it's best to have tests to help know if anything was broken. I would chose adding tests first and using things like the above solution as a bridge to getting both. – SamHennessy Jul 20 '15 at 09:02
9

Check something with echo, print() or printr() in the include file, header.php.

It might be that this is the problem OR if any MVC file, then check the number of spaces after ?>. This could also make a problem.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Saiyam Patel
  • 1,161
  • 9
  • 18
6

There are some problems with your header() calls, one of which might be causing problems

  • You should put an exit() after each of the header("Location: calls otherwise code execution will continue
  • You should have a space after the : so it reads "Location: http://foo"
  • It's not valid to use a relative URL in a Location header, you should form an absolute URL like http://www.mysite.com/some/path.php
James C
  • 14,047
  • 1
  • 34
  • 43
6

You are trying to send headers information after outputing content.

If you want to do this, look for output buffering.

Therefore, look to use ob_start();

Jendorski Labs
  • 447
  • 2
  • 9
  • 20
Pierre-Olivier
  • 3,104
  • 19
  • 37