1

I have a problem with 'setcookie' in PHP and I can't solve it.

so I receive this error "Warning: Cannot modify header information - headers already sent by (output started at C:\Program Files\VertrigoServ\www\vote.php:14) in C:\Program Files\VertrigoServ\www\vote.php on line 86"

and here is the file.. line 86 is setcookie ($cookie_name, 1, time()+86400, '/', '', 0); is there any other way to do this ??

<html>
<head>
<title>Ranking</title>
<link href="style.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#EEF0FF">
<div align="center"> 
<br/> 
<div align="center"><div id="header"></div></div>
<br/> 
<table width="800" border="0" align="center" cellpadding="5" cellspacing="0" class="mid-table"> 
    <tr><td height="5">
        <center> 
            </tr> 
            </table> 
        </center> 
    </td></tr> 
    <tr><td height="5"></td></tr> 
</table> 
<br/> 
<?php
    include "conf.php";

    $id = $_GET['id'];
    if (!isset($_POST['submitted']))
    {
        if (isset($_GET['id']) && is_numeric($_GET['id']))
        {

                    </div></td></tr> 
                    <tr><td align="center" valign="top"><img src="images/ads/top_banner.png"></td></tr> 
                </table> 
            </form> 
            <?php
        }
        else
        {
            echo '<font color="red">You must select a valid server to vote for it!</font>';
        }
    }
    else
    {
        $kod=$_POST['kod'];
        if($kod!=$_COOKIE[imgcodepage])
        {
            echo "The code does not match";
        }
        else
        {
            $id = mysql_real_escape_string($_POST['id']);
            $query = "SELECT SQL_CACHE id, votes FROM s_servers WHERE id = $id";
            $result = mysql_query($query) OR die(mysql_error());
            $row = mysql_fetch_array($result, MYSQL_ASSOC);
            $votes = $row['votes'];
            $id = $row['id'];
            $cookie_name = 'vote_'.$id;
            $ip = $_SERVER['REMOTE_ADDR'];
            $ltime = mysql_fetch_assoc(mysql_query("SELECT SQL_CACHE `time` FROM `s_votes` WHERE `sid`='$id' AND `ip`='$ip'"));
            $ltime = $ltime['time'] + 86400;
            $time = time();

            if (isset($_COOKIE['vote_'.$id]) OR $ltime > $time)
            {
                echo 'You have already voted in last 24 hours! Your vote is not recorded.';
            }
            else
            {
                $votes++;
                $query = "UPDATE s_servers SET votes = $votes WHERE id = $id";
                $time = time();
                $query2 = mysql_query("INSERT INTO `s_votes` (`ip`, `time`, `sid`) VALUES ('$ip', '$time', '$id')");
                $result = mysql_query($query) OR die(mysql_error());
                setcookie ($cookie_name, 1, time()+86400, '/', '', 0);
            }
        }
    }
?>
<p><a href="index.php">[Click here if you don't want to vote]</a></p><br/>
<p><a href="index.php">Ranking.net</a> &copy; 2010-2011<br> </p> 
</div> 
</body> 
</html> 

Thanks a lot!

Ranking
  • 13
  • 5
  • Blast from the past: `cellpadding`, `bgcolor` etc. – fredley Mar 20 '11 at 00:07
  • 1
    possible duplicate of [Warning: Cannot modify header information - headers already sent...](http://stackoverflow.com/questions/3190833/warning-cannot-modify-header-information-headers-already-sent) – mario Mar 20 '11 at 00:10

5 Answers5

4

You cannot have any output before header() and setcookie() calls.

https://stackoverflow.com/search?q=+headers+already+sent+by
https://stackoverflow.com/tags/php/info

Any output includes any <html> before the openeing <?php marker, or any print or echoing of content. Another culprit is the UTF-8 BOM http://en.wikipedia.org/wiki/Byte_Order_Mark - which most text editors do not show visibly, but confuses PHP when at the beginning of files.

Community
  • 1
  • 1
mario
  • 144,265
  • 20
  • 237
  • 291
  • @Charles: Indeed. Search indicates that's the worst offender. (The real problem are text editors though. Luckily mine reveals it visibly as ****.) – mario Mar 20 '11 at 01:53
2

Setting a cookie requires sending a header to the client, and you can't send headers if the output has already started.

You have to put the PHP code before the HTML markup so that you can call setcookie before any output is sent and you also separate PHP code from presentation which you should do anyway.

Matteo Riva
  • 24,728
  • 12
  • 72
  • 104
  • Matteo, I'm newbie in PHP, how can I separate the code ? If you don't mind can You show me an exemple ? – Ranking Mar 20 '11 at 00:10
  • @Ranking here I posted a complete example how to do it, and also some reasons why should you do it this way, not using ob_start as an ugly crutch: http://stackoverflow.com/questions/5183163/using-php-include-to-separate-site-content/5183401#5183401 – Your Common Sense Mar 20 '11 at 00:26
1

You should put the cookie code at the top of the page. A better layout would be something like this:

<?php
//include config

//check posted data (included settings cookies)


//set needed variables
?>
<html>
.....

You could also separated the php code and html. This is generally what i do. My uses generally involve a view class or (in the past) smarty. but a quick example would be to add this code at the bottom of the above php code and get rid of the html:

<?php               

  if(empty($tpl)) {
    $tpl = 'index';
  }

  if(file_exists("template/{$tpl}.tpl.php")) {
    include("template/{$tpl}.tpl.php");
  }
  else {
    header('Location: /');
  }

?>

YOu would need to create a directory called 'templates' and add the html code to files that end in the .tpl.php extension. Really they are just php pages, but the .tpl. part help you remember that its just mark up. Make them php pages (not html) so you can output variables

Then in your varios parts of your code above you would set $tpl to be the template you want to load.

This is a just a base bit of code, but it should give you a general idea on how to separate this data. THe main idea is that all html and text will be outputted "after" all programming code has been done.

dbers
  • 636
  • 5
  • 16
0

You can not use PHP to set a cookie after any thing has been outputted, and the html before the first php tag does count as output. to keep to a purely php method you'd have to move the whole part about determining what to put int he cookie and setting it up to the very top. or what I do in situations where that would require to much extra work to do it that way is to have php echo out the JavaScript code to set a cookie. now if you make or get a nice JS cookie setting function and either embed it or link it into the page. then all you have to do is have php echo the function call with the proper data in it at that point. then when the page loads while php still will not set the cookie, but when the browser when it runs the js code it will. and so you get what you want the cookie is set. and you did not have to move the stuff up to the top.

Kit Ramos
  • 1,533
  • 1
  • 15
  • 32
0

What you need to do is to create a nice buffer to hold all the headers in until you are down processing. ob_start does the job for you and here is a reference to it. http://php.net/manual/en/function.ob-start.php

When you are finished loading all the different headers use ob_get_contents like this $text = ob_get_contents(); echo($text); ob_end_clean();

I hope this helps.

  • +1 That's a workaround, but intended exactly for that, and probably a good fit for OP. The last example commands are probably equivalent to just `ob_end_flush();` I think. – mario Mar 20 '11 at 00:22
  • In fact, it's ugly crutch, and it's purpose is far away from solving such silly problems. The only proper solution is using proper page layout. – Your Common Sense Mar 20 '11 at 00:27