-3

我试图为我的页面的访问编写一个计数器,它每天只计算每个 IP 一次。我转录了一个找到的代码来了解它是如何工作的,并在以后实现一些其他功能。不幸的是,我的新代码不起作用。

我从中制作的代码:

<?php
$timeReset = 86400; //24h
$ipPath = "ipsafe.txt";
$countPath = "counts.txt";
$timePath = "time.txt";

$ip = $REMOTE_ADDR;
$time = time();
$resetTime = $time+$timeReset;

$timeFile = fopen($timePath, "r+");
$timeData = fread($timeFile, filesize($timePath));
//if resetTime is passed -> Reset
if($time >= $timeData) {
    //clear ipSafe
    $ipFile1 = fopen($ipPath, "w+"); 
    fclose($ipFile);
    //set new resetTime
    rewind($timeData);
    fwrite ($timeData, $resetTime);
}
fclose($timeFile);

//creat IP-List
$ipData = file($ipPath);
while (list ($line_num, $line) = each ($ipData)) {
    $digits = explode(",",$line);
}
//if IP was not saved in last timeframe
if(!in_array($ip, $digits))
{
    //write new IP
    $ipFile2=fopen($ipPath, "a+");
    @flock($ipFile1,2);
    fwrite($ipFile2, "$ip".",");
    @flock($ipFile1,3);
    fclose($ipFile2);
    //increment counter
    $countFile = fopen($countPath,"r+");
    $countData = fread($countFile, filesize($countPath);
    rewind($countFile);
    $countData++;
    fwrite($countFile, $countData);
    fclose($countFile);
}
?>

有以下问题:

  • 我的代码有什么问题?

  • flock 用于管理对文件的访问,但是为什么我要为同一个文件使用不同的名称呢?

感谢您的建议。

编辑:

很抱歉在解释问题时如此不具体。集成调试器后,我将“REMOTE_ADDR”更改为“$_SERVER['REMOTE_ADDR']”,因此修复了 1 个错误。现在我遇到了以下问题:

Warning: fopen(time.txt): failed to open stream: No such file or directory in .../counter.php on line 15

但是该文件与 counter.php 位于同一目录中-当然 fread 和 filesize 也失败了

Warning: fopen(ipsafe.txt): failed to open stream: Permission denied in .../counter.php on line 20

该文件尚不存在,但我认为“fopen($ipPath, "w+");" 如果它不存在则创建它。

Fatal error: Call to undefined function fb() in .../counter.php on line 26

不是“fb($timeFile);” 将值发送到 firePHP?

4

1 回答 1

0

不进行完整的代码审查(这将导致几乎完全重写您的代码),我建议您更改以下内容以解决您列出的问题:

以下行使用$REMOTE_ADDR未定义的 。

$ip = $REMOTE_ADDR;

您很可能打算使用$_SERVER['REMOTE_ADDR'](您已通过编辑确认),因此该行应为:

$ip = $_SERVER['REMOTE_ADDR'];

您声明您在尝试打开time.txt文件时收到错误消息:“没有这样的文件或目录”。您还说该文件与counter.php- 存在于同一目录中,但您仍然收到此错误。这可能意味着两件事之一;首先,文件不存在,你错了;第二,您的 counter.php 文件与执行它的任何脚本位于不同的目录中 - 这意味着该time.txt文件需要位于执行脚本的目录中。我会为此推荐两件事。

首先,如果文件确实存在,请为其使用绝对路径:

$timePath = '/path/to/your/files/time.txt';

第二,验证文件是否存在(在代码中),如果不存在,则创建它。fopen()with r/ r+flags如果文件不存在,则不会创建文件,因此需要手动进行。尝试将代码更改为以下内容:

if (!file_exists($timePath)) touch($timePath);
$timeFile = fopen($timePath, 'r+');
if ($timeFile) {
    // the rest of your code
}

您说打开ipsafe.txt文件时收到错误消息:“权限被拒绝”。这是一个有趣的;虽然行号与您的示例代码不匹配,但我相信这些是有问题的行:

//clear ipSafe
$ipFile1 = fopen($ipPath, "w+"); 
fclose($ipFile);

第一个问题是您永远不会$ipFile1在代码中使用(除了错误地锁定/解锁它;有关该信息,请参见下文)。第二个是你打电话fclose($ipFile);。没有句柄命名$ipFile!您可以删除这些代码行!

您尝试rewind使用文件中的文件指针time.txt写入新时间,但是,您使用的是从文件中读取的值$timeData- 而不是文件本身$timeFile。将这些行更新为以下内容:

rewind($timeFile);
fwrite($timeFile, $resetTime);

您再次读取文件ipsafe.txt以查看完整的 IP 地址列表 - 如果当前用户的 IP 不在其中,则添加它。这可能是一个逻辑问题,但您检查文件最后一行的 IP 地址 - 但您仍会遍历项目的每一行。根据代码中的注释://if IP was not saved in last timeframe,我将假设这是您打算做的 - 但以防万一 - 我建议将if出现在循环下方的完整 -statement 块移动到循环内部。

这是有趣的块:

//write new IP
$ipFile2=fopen($ipPath, "a+");
@flock($ipFile1,2);
fwrite($ipFile2, "$ip".",");
@flock($ipFile1,3);
fclose($ipFile2);

您将文件打开到$ipFile2( 2 ),然后锁定一个完全不同的文件$ipFile1( 1 ),写入2,解锁1,然后关闭2。我认为您的意图是锁定/解锁2,这在这里非常有意义,因此我建议您更改$ipFile1$ipFile2这些行。

那应该(可能)做到这一点。毕竟,代码应该类似于:

<?php
$timeReset = 86400; //24h
$ipPath = "ipsafe.txt";
$countPath = "counts.txt";
$timePath = "time.txt";

$ip = $_SERVER['REMOTE_ADDR'];
$time = time();
$resetTime = $time+$timeReset;

if (!file_exists($timePath)) touch($timePath);
$timeFile = fopen($timePath, "r+");
if ($timeFile) {
    $timeData = fread($timeFile, filesize($timePath));
    //if resetTime is passed -> Reset
    if($time >= $timeData) {
        //set new resetTime
        rewind($timeFile);
        fwrite ($timeFile, $resetTime);
    }
    fclose($timeFile);

    //creat IP-List
    $ipData = file($ipPath);
    while (list ($line_num, $line) = each ($ipData)) {
        $digits = explode(",",$line);
    }
    //if IP was not saved in last timeframe
    if(!in_array($ip, $digits)) {
        //write new IP
        $ipFile2=fopen($ipPath, "a+");
        @flock($ipFile2, LOCK_EX);
        fwrite($ipFile2, "$ip".",");
        @flock($ipFile2, LOCK_UN);
        fclose($ipFile2);
        //increment counter
        if (!file_exists($countPath)) touch($countPath);
        $countFile = fopen($countPath,"r+");
        if ($countFile) {
            $countData = fread($countFile, filesize($countPath);
            if (empty($countData)) $countData = 0; // initialize the counter to '0' if it hasn't been set
            rewind($countFile);
            $countData++;
            fwrite($countFile, $countData);
            fclose($countFile);
        }
    }
}
?>

$resetTime现在,关于您的变量,我还有一个额外的逻辑问题。理想情况下,增加一天是给给定时间戳增加 24 小时(24 小时 = 86400 秒)。但是,夏令时将打破这一点。而不是执行以下操作:

$resetTime = time() + 86400;

尝试走不同的路线(如果您对此感到担心,那就是):

$resetTime = strtotime('+1 day');
于 2012-10-01T14:58:46.537 回答