duanjia1870
duanjia1870
2015-01-02 22:14

PHP的setcookie()函数不起作用。 怎么了?

已采纳

I really need some help here. I wrote this script to track my website's traffic. I was using cookies to help the server know when a client has visited a page once already for the day, which allowed me to track visitors by two (2) counters/categories: UNIQUE hits and "REFRESH" hits.

I store the information in directories named by date. For example, the file located at www.example.com/counter/unique/2015/12/31/about would store a number like 62, which would mean I got 62 unique hits to the about.php page on December 31st, 2015.

Each page calls the script counter.php. Everything seems to work fine, but both of my counters continue to read the same number, as if every hit is unique. I knew something was wrong when I saw the two sets of numbers, and I confirmed it by refreshing the index page several times. What it means is that the cookies are not being set. The PHP script in counter.php tests for the cookie to see if it has been set. I have been also checking the cookies from my browser settings and it shows no cookies. I refresh each page several times and re-check for the cookies several times, but still no luck!

What in the world is going on here?!? It was working before!

The following shows how each page calls the counter.php script:

http://www.example.com/index.php:

<?php
    include_once("log/counter.php");
?>
<!doctype html>
<html>
...
</html>

The following is my PHP code called counter.php:

http://www.example.com/log/counter.php

<?php

    // THIS LINE WAS NOT PART OF MY ORIGINAL SCRIPT
    ob_start();

    // THIS IS THE PAGE THAT IS CALLING THIS SCRIPT,
    // FOR EXAMPLE: ABOUT, INDEX, CONTACT, ETC.
    $page = basename($_SERVER["SCRIPT_FILENAME"], ".php");

    // THE DIRECTORY WHERE THIS SCRIPT IS LOCATED
    // RELEVANT TO THE CALLING PAGE
    $cwd = dirname(__FILE__) . "/counter/";

    date_default_timezone_set('America/Chicago');
        // TIMEZONE FOR HOUSTON, TEXAS. THIS WAY, ALL
        // DATE & TIME INFO IS SET IN THAT TIMEZONE

    $currentYear = date("Y");   // EX: 2015
    $currentMonth = date("m");  // EX: 12
    $currentDay = date("d");    // EX: 31

    // THIS PREPARES THE DIRECTORY FOR TODAY'S DATE
    $today = $currentMonth."/".$currentDay."/".$currentYear;
    $current = $currentYear."/".$currentMonth."/".$currentDay."/";

    $currentHour = date("H");
    $currentMinute = date("i");
    $currentSecond = date("s");

    // THE FOLLOWING IS USED FOR THE COOKIE EXPIRATION PARAM

    $secondsRemaining = 60 - $currentSecond;
    $minutesRemaining = 59 - $currentMinute;
    $hoursRemaining = 23 - $currentHour;

    $totalSecondsRemaining = ($hoursRemaining * 60 * 60) + ($minutesRemaining * 60) + $secondsRemaining;

    if ($totalSecondsRemaining<=0) { $totalSecondsRemaining = 86400; }
        // 86400 SECONDS = 24 HOURS / 1 DAY

    $ucFile = $cwd . "unique/" . $current . $page;      // UNIQUE-HITS COUNTER
    $rcFile = $cwd . "refresh/" . $current . $page;     // REFRESH-HITS COUNTER

        // MAKE SURE ALL DIRECTORIES EXIST
        if (!file_exists($cwd."unique/")){
            mkdir($cwd."unique", 0755);
        }
        if (!file_exists($cwd."unique/".$currentYear)){
            mkdir($cwd."unique/".$currentYear, 0755);
        }
        if (!file_exists($cwd."unique/".$currentYear."/".$currentMonth)){
            mkdir($cwd."unique/".$currentYear."/".$currentMonth, 0755);
        }
        if (!file_exists($cwd."unique/".$currentYear."/".$currentMonth."/".$currentDay)){
            mkdir($cwd."unique/".$currentYear."/".$currentMonth."/".$currentDay, 0755);
        }
        if (!file_exists($cwd."refresh/")){
            mkdir($cwd."refresh", 0755);
        }
        if (!file_exists($cwd."refresh/".$currentYear)){
            mkdir($cwd."refresh/".$currentYear, 0755);
        }
        if (!file_exists($cwd."refresh/".$currentYear."/".$currentMonth)){
            mkdir($cwd."refresh/".$currentYear."/".$currentMonth, 0755);
        }
        if (!file_exists($cwd."refresh/".$currentYear."/".$currentMonth."/".$currentDay)){
            mkdir($cwd."refresh/".$currentYear."/".$currentMonth."/".$currentDay, 0755);
        }
        // ALL DIRECTORIES NOW EXIST. SO FAR, NO PROBLEMS!


    // UNIQUE COUNTER...
    if (!isset($_COOKIE[$page])){          // THIS ALWAYS GETS CALLED...
        if (file_exists($ucFile)){         // IF PAGE HAS BEEN COUNTED...
            $file = fopen($ucFile, "r+");  //  1. OPEN THE COUNTER FILE FOR PAGE
            $count = fgets($file);         //  2. GET THE CURRENT COUNT
            fclose($file);                 //  3. CLOSE THE FILE
            $file = fopen($ucFile, "w");   //  4. RE-OPEN FILE AND CLEAR IT
            fputs($file, $count+1);        //  5. REPLACE WITH CURRENT COUNT+1
        }
        if (!file_exists($ucFile)){        // IF THIS IS THE FIRST TIME TODAY...
            $file = fopen($ucFile, "w");   //  1. CREATE A COUNTER FOR THIS PAGE
            fputs($file, "1");             //  2. PUT 1 AS THE CURRENT COUNT
        }

        $works = setcookie($page, "Today is ".$today, $totalSecondsRemaining);
            // SET A COOKIE INDICATING THAT THIS PAGE HAS BEEN
            // VISITED ALREADY BY THIS GUEST.
    }


    // REFRESH COUNTER...
    if (file_exists($rcFile)){             // IF PAGE HAS BEEN COUNTED...
        $file = fopen($rcFile, "r+");      //  (REPEAT STEPS ABOVE, 1-5)
        $count = fgets($file);
        fclose($file);
        $file = fopen($rcFile, "w");
        fputs($file, $count+1);
    }
    if (!file_exists($rcFile)){
        $file = fopen($rcFile, "w");
        fputs($file, "1");
    }

    // AGAIN, NOT PART OF THE ORIGINAL SCRIPT.
    ob_end_flush();

    // ALWAYS RETURNS TRUE...
    echo "<!-- $works -->";
?>

I have tried everything I can think of to get this script working again. To the best of my knowledge, I never changed anything in the code; it just stopped working one day.

So, what I've already checked so far is:

  • I know there is NO output before the headers are sent.
  • I know that PHP thinks the cookie is being set, because setcookie() returns true
  • I know the cookie expiry date is set in the future.
  • I know the expiry date is NOT larger than PHP's integer max-size
    • PHP Integer maximum value is about 32 bits, mine is no more than 5 characters
  • I know that neither www.example.com nor simply example.com change the script's behavior

I have also tried the following:

setcookie($page, "Today is ".$today, $totalSecondsRemaining);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/");
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "");

setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "mywebsite.com");
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", ".mywebsite.com");
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "*.mywebsite.com");
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "www.mywebsite.com");

setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "mywebsite.com", 0);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", ".mywebsite.com", 0);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "*.mywebsite.com", 0);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "www.mywebsite.com", 0);

setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "mywebsite.com", false);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", ".mywebsite.com", false);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "*.mywebsite.com", false);
setcookie($page, "Today is ".$today, $totalSecondsRemaining, "/", "www.mywebsite.com", false);

I isolated the problem to the PHP setcookie() function. Any help is really, really, greatly appreciated.

P.S.

Admittedly, I'm sure that it would be better to store this information in a MySQL Database, but I'll work on that once I get this problem fixed.

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • dongshadu4498 dongshadu4498 6年前

    I know the cookie expiry date is set in the future. I know the expiry date is NOT larger than PHP's integer max-size PHP Integer maximum value is about 32 bits, mine is no more than 5 characters

    Uh, shouldn't the expiry time of a cookie be the number of seconds since epoch? A 5 digit expiry date would be early January 2nd, 1970, so I don't think it's possible that your expiry date is both five characters or less, and also in the future.

    http://php.net/manual/en/function.setcookie.php:

    This is a Unix timestamp so is in number of seconds since the epoch. In other words, you'll most likely set this with the time() function plus the number of seconds before you want it to expire

    <?php
    setcookie("hiworld", "true", time()+300);
    ?>
    Hi, world!
    
    
    curl -v danf.us/t.php
    * Adding handle: conn: 0x7ff05180d000
    * Adding handle: send: 0
    * Adding handle: recv: 0
    * Curl_addHandleToPipeline: length: 1
    * - Conn 0 (0x7ff05180d000) send_pipe: 1, recv_pipe: 0
    * About to connect() to danf.us port 80 (#0)
    *   Trying 66.191.143.117...
    * Connected to danf.us (66.191.143.117) port 80 (#0)
    > GET /t.php HTTP/1.1
    > User-Agent: curl/7.30.0
    > Host: danf.us
    > Accept: */*
    >
    < HTTP/1.1 200 OK
    * Server nginx/1.0.10 is not blacklisted
    < Server: nginx/1.0.10
    < Date: Fri, 02 Jan 2015 22:31:19 GMT
    < Content-Type: text/html
    < Transfer-Encoding: chunked
    < Connection: keep-alive
    < Keep-Alive: timeout=20
    < X-Powered-By: PHP/5.3.13-pl0-gentoo
    < Set-Cookie: hiworld=true; expires=Fri, 02-Jan-2015 22:36:19 GMT
    <
    Hi, world!
    * Connection #0 to host danf.us left intact
    
    点赞 评论 复制链接分享