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