Problem with cookie reset logic

What am I doing wrong here? I’m practicing cookies and want to set a cookie that holds the number of visits a user has done, increment it on each new visit, and restart it and show a welcome message when either someone is a new visitor or has reset their cookies themselves. The problem is, the cookie gets reset, but the welcome message is not shown at all and just the string “You’ve visited this website…times before” is shown. I’m suspicious about the use of header, I think that’s the thing that causes this but I don’t know how. Anyone could help?

<?php
if(isset($_COOKIE['visits']) && isset($_GET['restart'])){
    if($_GET['restart']=='true') {
        setcookie('visits',null,time()-24*3600*365,'/');
        unset($_COOKIE['visits']);
        header("Location: test-remove-cookie-faulty.php");
        //exit; --> Someone told me to do this but it just exacerbated the issue.
    }
}
if(!isset($_COOKIE['visits'])){
    $visits = 1;
    setcookie('visits',$visits,time()+24*3600*365);
    echo "Welcome To This Website";
}
else{
    $visits = $_COOKIE['visits']+1;
    setcookie('visits',$visits,time()+24*3600*365);
    echo "You've visited this website ".$_COOKIE['visits']. ' times before.<br>';
    echo "<a href='?restart=true'>Restart</a><br>";
}

You do need to have the exit() in there, though, otherwise execution will continue through your code. I would have expected it to show the “Welcome” message, though, unless the cookie is still being seen as existing until the browser outputs the headers.

I’m not really able to understand what you’re saying in the end of your answer, the English grammar you’ve used there is a bit complicated for me :smiley: No kidding, I’m saying that honestly.
But anyway I read a bit more about how HTTP requests work and I think I’ve finally managed to make sense out of how this (aweful) code (read: mess!) runs. It turns out that I missed many important points. Now I’m going to clarify it a bit for anyone else who may come across this post in future:

  1. First time the user visits the website, the middle part of code is run, thus the cookie is set with value 1 and a welcome message is shown. However, from first time on, the user won’t be able to see the welcome message any time again. Here’s why:
  2. On second visit, the bottom part of the code is run, thus a “You’ve visited this website 1 times before” is shown. Now let’s assume the user refreshes the page once, and sees the incremented number 2, and then 3, and so on and finally at some point uses the Restart hyperlink. Here’s what happens next:
  3. The top part of the code is run and the cookie is destroyed, but here now a “redirect browser header” is sent to the browser and has it make another request to the address specified(which is the address of the same script in my case), however, the rest of the script gets executed too on the server after the header is sent. Thus the middle block is run and the cookie is set with the value 1, but no welcome message is shown because the response has been sent to the browser already! and this time when the browser makes the request we asked it to, because the cookie is set and $_GET[‘restart’] is not set the bottom part of the code is run which results in incrementing the $_COOKIE value and seeing the “You’ve visited this website 2 times before” once again instead of the welcome message. Right? Not completely. Although it doesn’t show the welcome message, but neither shows the number 2! It shows the number 1. You can test this mess yourself! The reason is Just at the time that you call the PHP setcookie() function it doesn’t affect the $_COOKIE superglobal array, it’s filled only by the browser when a request has been made. Thus you see the number 1 again which means I’ve accidentally done it right and the result shown is what I wanted.. I got lucky at least at this part :smile:
    I hope i’m not really bad at explaining things but that’s basically how it works. :slight_smile:
1 Like

Now my next attempt was to find out what was happening when I added that exit; as well after the header function, which caused it to lead to an unwanted behavior again.(Number of visits keep incrementing)
The final guess I’ve come up with right now is that when using a redirect header, the browser does the redirection request before setting the received cookies. Otherwise, I can’t think of anything else that may cause this behavior. Anyone could please comment on this and make it clear?

What I was thinking ( in the comments I’ve added)

<?php
if(isset($_COOKIE['visits']) && isset($_GET['restart'])){
    if($_GET['restart']=='true') {
 // ** Your code sees the "restart" cookie and does this bit
        setcookie('visits',null,time()-24*3600*365,'/'); // ** sets a value for this cookie
        unset($_COOKIE['visits']);  // ** and then immediately deletes it. Why not just delete it?
        header("Location: test-remove-cookie-faulty.php"); // ** then sends a header
        //exit; --> Someone told me to do this but it just exacerbated the issue.
        // ** Because you don't exit on the line above, program execution continues
    }
}
if(!isset($_COOKIE['visits'])){
   // ** This is where I'd expect the execution to continue, because you deleted the cookie further up
    $visits = 1;
    setcookie('visits',$visits,time()+24*3600*365);
    echo "Welcome To This Website";
}
else{
  // ** but you say this is where it continues, where it says "you've visited before"
  // ** so I can only assume that until the script ends, the cookie still exists, it doesn't actually
  // ** get deleted yet.
    $visits = $_COOKIE['visits']+1;
    setcookie('visits',$visits,time()+24*3600*365);
    echo "You've visited this website ".$_COOKIE['visits']. ' times before.<br>';
    echo "<a href='?restart=true'>Restart</a><br>";
}
1 Like

@droopsnoot Thanks. Yes that exit; is important. I just didn’t understand it at the time I asked this question.
I asked about my problem with this code somewhere else too and someone told me that this is happening because in some server/client combinations the redirect is occurring before the browser has a chance to set the cookie. It depends on your webserver, e.g. IIS vs Apache. Pushing some content to the browser along with the headers gives it a chance to process the cookie, so you must (obviously enable output buffering in your php.ini) and then use ob_start() and ob_end_flush() before and after the header setting. Or simply just echoing a dot echo "."; directly before the header(... line to ensure some communication with the client before they are redirected.
I tested both of these and neither worked.
Another probability is that it is a browser bug, because I’m seeing a “Failed to load response data” in Chrome dev tools in the 302 header in the network tab, and Googling it shows that others have had the same issue too. So all in all, I think I’m not going to waste more time on it. I learned a lot from it anyway.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.