【问题标题】:PHP hitcounter adds symbol before digit for each hitPHP hitcounter在每次点击的数字前添加符号
【发布时间】:2023-05-09 16:51:01
【问题描述】:

我遇到了一个小问题。我有一个 php 页面:

index.php

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<?php
include( 'counter.php' );
?>
</body>
</html>

还有文件counter.php

<?php
$fp = fopen("counter.txt", "r+");

if(!$fp){
    error_log("Could not open counter.txt");
    exit();
}

if(!flock($fp, LOCK_EX)) {  // acquire an exclusive lock
    error_log("Could not lock");
}
else{
    $counter = intval(fread($fp, filesize("counter.txt")));
    $counter++;

    echo $counter;
    ftruncate($fp, 0);      // truncate file
    fwrite($fp, $counter);  // set your data
    fflush($fp);            // flush output before releasing the lock
    flock($fp, LOCK_UN);    // release the lock
}
fclose($fp);
?>

以及文件counter.txt,其内容为“0”(0)

运行一次index.php后,文本文件内容变为^@^@1,之后变为^@^@^@1

我想要的是0变成1,然后是2

代码有问题吗?

它在 Ubuntu 18 上运行,带有 Apache,并且具有权限的文件是

-rw-rw-r-- 1 emanuel www-data  559 Feb 13 21:56 counter.php
-rw-rw-r-- 1 emanuel www-data   11 Feb 13 22:51 counter.txt
-rw-rw-r-- 1 emanuel www-data  128 Feb 13 22:50 index.php
drwxrwxr-x 2 emanuel www-data 4096 Feb 12 14:55 software

不胜感激

【问题讨论】:

  • 就我个人而言,我会使用 file_get_contentsfile_put_contentsLOCK_EX 标志。 - 但那是我。它还会将您的代码减少一半。
  • the textfile content becomes ^@^@1, echo 语句是怎么说的?
  • 谢谢@ArtisticPhoenix,回声说“1”
  • 您是否 100% 确定没有其他代码正在修改此文件?
  • 此外,您应该将$counter 显式转换为字符串(string) $counter,并且可以使用declare(strict_types=1) 约束。如果文件不存在,则进一步创建文件,并在文件为空时使用$counter = ($fsize = filesize("counter.txt")) ? intval(fread($fp, $fsize)) : 0; 初始化计数器。否则fread 由于大小为零而引发错误。

标签: php fopen fwrite flock hitcounter


【解决方案1】:

在 ftruncate 后使用 Rewind(需要一些工作来隔离它)

    ftruncate($fp, 0);      // truncate file
    rewind($fp); //rewind the pointer

或者您可以只使用rewind 而不是ftruncate,这似乎是\0 空字节的原因。两者都做似乎毫无意义,就好像你在倒带后写它无论如何都会擦除文件(除非你使用a+ append)......

查看文档的第一个示例同时使用两者。

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

来自 PHP.net

<?php
$handle = fopen('output.txt', 'r+');

fwrite($handle, 'Really long sentence.');
rewind($handle);
fwrite($handle, 'Foo');
rewind($handle);

echo fread($handle, filesize('output.txt'));

fclose($handle);
?>

即使没有解释原因...我只是使用rewind(),但我总是很懒,所以我尽量写我需要的最少代码,因为我写了很多代码。

另一种解决方案

在使用intval之前修剪文件的内容

  $counter = intval(trim(fread($fp, filesize("counter.txt"))));

在记事本++中

  [null][null]1

无论如何,这很有趣...谢谢!

【讨论】:

  • 这不会阻止竞争条件下的并发。两个实例可以同时读取,但结果只会是 +1。如问题所示锁定是执行此类任务的正确方法。
  • 这是一个很好的观点......但有时看看问题是否与“这个”代码或其他地方有关。我看不出问题的任何原因,如果它在使用 file_put_contents 时发生,那么其他一些代码正在修改文件。
  • 您好,我删除了 code.php 中的结尾?> - 无效
  • 哈,我猜我们都学到了一些东西,不要告诉任何人我在 9 年的 PHP 编程中从未使用过 ftruncate ... 哈哈 ... 或者如果我这样做了,我会忘记它。
  • 如果您不想删除替代(坏)解决方法,我建议将正确的解决方案和问题解释移到顶部。
最近更新 更多