计数器与IP块通过文件 - PHP

时间:2012-09-27 21:19:38

标签: php

我试图为我的页面访问写一个计数器,每天只计算一次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?

1 个答案:

答案 0 :(得分: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() / r标记r+如果不存在则不会创建文件,因此这需要是手动的。尝试将代码更改为以下内容:

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 - 语句块出现在循环内部的循环内部。

这是有趣的块:

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

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

应该这样做(可能)。在所有事情之后,代码应该类似于:

<?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小时= 86400秒)增加24小时。但是,夏令时会破坏这一点。而不是做以下事情:

$resetTime = time() + 86400;

尝试不同的路线(如果你担心这个,那就是):

$resetTime = strtotime('+1 day');