带有日期的PHP命中计数器
我将以下代码用于命中计数器:带有日期的PHP命中计数器,php,file,web,Php,File,Web,我将以下代码用于命中计数器: $fp = fopen("counterlog.txt", "r"); $count = fread($fp, 1024); fclose($fp); $count = $count + 1; $fp = fopen("counterlog.txt", "w"); fwrite($fp, $count); fclose($fp); 在该文件中,我只有一个编号,但我希望通过以下方式获得一个文件: 18/09/2015 10 19/09/2015 1
$fp = fopen("counterlog.txt", "r");
$count = fread($fp, 1024);
fclose($fp);
$count = $count + 1;
$fp = fopen("counterlog.txt", "w");
fwrite($fp, $count);
fclose($fp);
在该文件中,我只有一个编号,但我希望通过以下方式获得一个文件:
18/09/2015 10
19/09/2015 11
因此,我希望计数按日期分组,并用制表符分隔日期
我知道我可以使用数据库来实现这一点,但在这种特定情况下,我只想使用文本文件
是否有可能获得?fwrite($fp,date('d/m/Y')。$count) 希望这对你有帮助
<?php
$today = date('d/m/Y');
$dd=null;
$fp = fopen("test.txt", "r");
if ($fp) {
while (($line = fgets($fp)) !== false) {
$dd[] = explode(' ', $line);
}
} else {
}
fclose($fp);
$fw = fopen('test.txt', 'w');
if(is_array($dd) && count($dd) > 0){
foreach ($dd as $key => $value) {
$cc = $value[1];
if($today == $value[0])
{
$cc++;
}
fwrite($fw,$value[0].' '.$cc);
}
}else
{
fwrite($fw,$today.' 0');
}
fclose($fw);
exit;
?>
iam所做的是,逐行读取文件数据并制作一个数组,然后再次写入,当天计数将分组我建议不要为此使用文件。如果两个请求几乎同时发出,则可能会损坏文件。当然,您可以使用锁来解决这个问题,但是数据库可以更好地解决这个问题 我想说的是使用csv格式。这至少是一种正式的格式,允许您更轻松地读写
$fp = fopen( "counter.txt", "r" );
while( !flock( $fp, LOCK_EX ) ) {
}
$csv = Array();
$currentdate = date( "d/m/Y" );
$rowavailable = FALSE;
while( ($row = fgetcsv( $fp, 100, " " )) !== FALSE ) {
if( $row[0] == $currentdate ) {
$row[1] = $row[1] + 1;
$rowavailable = TRUE;
}
$csv[] = $row;
}
fclose( $fp );
if( !$rowavailable ) {
$newrow = Array( $currentdate, 1 );
$csv[] = $newrow;
}
$fp = fopen( "counter.txt", "w" );
for( $csv as $row ) {
fputcsv( $fp, $row, " " );
}
fclose( $fp );
flock( $fp, LOCK_UN );
这应该符合你的要求
<?php
$dateexists = false;
if(!file_exists('counterlog.txt'))
{
$fh = fopen('counterlog.txt', 'w');
fclose($fh);
}
$datecounts = file('counterlog.txt', FILE_IGNORE_NEW_LINES);
foreach($datecounts as $key => $datecount){
list($date, $count) = explode("\t", $datecount);
$count = (int) $count;
if($date == date('d/m/Y'))
{
$datecounts[$key] = $date."\t".++$count;
$dateexists = true;
}
}
if(!$dateexists)
{
$datecounts[] = date('d/m/Y')."\t1";
}
$fh = fopen('counterlog.txt', 'w');
if (flock($fh, LOCK_EX)) {
foreach($datecounts as $datecount)
{
fwrite($fh, $datecount.PHP_EOL);
}
flock($fh, LOCK_UN);
}
else
{
//couldn't lock, might want to do stuff here
}
fclose($fh);
除了@Sumurai8立即使用CSV的答案外,还可以进一步减少代码。将文件读入assoc数组的正则表达式非常简单:
$file = file_get_contents("cnt.txt", LOCK_EX);
preg_match_all("/^ ([\d/-]+) \s+ (\d+) /mix", $file, $dc);
$date_counts = array_combine($dc[1], $dc[2]);
拥有[“2015-11-11”=>22,…]
阵列可以简化将每个日期计数器更新为:
$date = date("Y-m-d"); // proper ISO format
$date_counts[$date] += 1; // extra notice for first hit
使用将其写回也变得相当容易,并稍微简化了锁定:
array_walk(
$date_counts,
function(&$cnt, $date) {
$cnt = "$date $cnt";
}
);
$file = implode("\n", $date_counts);
// add another fopen/flock/LOCK_SH here
file_put_contents("cnt.txt", $file, LOCK_EX);
请注意,这仍然不是原子写入。(但不使用数据库是你的决定和问题,不是我的。)如果你不想使用数据库(你真的应该这样做),那么至少添加文件锁定()。虽然您可以按行存储日期+计数,但只使用JSON或serialize()进行文件存储也会更简单。但我必须验证最后一行日期是否相同。如何添加文件锁定?@helloimyourmind我已使用文件锁定更新了我的答案。谢谢,但这不会更新计数,总是1。我发现了一个问题:当日期改变时,“date+1”存储在过去的一天附近,而不是新的一行。有什么问题吗?@helloimyourmind现在应该可以用了。添加换行符的位置有问题。关于你的开场白,脚本请求不是由队列中的服务器按顺序处理的吗?我同意数据库将是这里的最佳解决方案。@MartynShutt幸运的是没有。如果stackoverflow在php上运行,您会说我们大多数人都不会看到任何东西。查找线程,例如http deamon的“threadlimit”,如Apache.Ah,多线程。谢谢我将进一步深入探讨这个话题。