【问题标题】:Getting abnormal error in Page View Counter using PHP使用 PHP 在页面查看计数器中获取异常错误
【发布时间】:2021-01-04 09:33:44
【问题描述】:

我在 .txt 文件中有 fwrite 的页面浏览计数器脚本,我在另一个文件中回显它,我必须在其中显示页面浏览量。计数器更新脚本是:

$handle = fopen("counter.txt", "r");
if(!$handle){

    echo "could not open the file" ;

} else {

    $counter = (int ) fread($handle,20);
    fclose ($handle);
    $counter++;
    $handle = fopen("counter.txt", "w" );
    fwrite($handle,$counter) ;
    fclose ($handle) ;
}

以上代码在文件名counter.txt中写入(fwrite)页面浏览量

而且我要显示页面浏览量的页面也是 HTML 和 PHP 的组合。我在那里添加的代码如下读取视图并显示它

$handle = fopen("counter.txt", "r"); 
if(!$handle){ 
    echo "could not open the file" ; 
} else { 
    $counter = ( int ) fread ($handle,20) ; 
}

echo $counter;

上面的代码显示了页面浏览量。它从counter.txt 文件中读取并显示页面浏览量。

为此我收到异常错误。当我尝试通过desktop 访问文件时,它显示错误的页面视图。它增加了额外的1 视图。例如如果只有1 页面视图,则显示2

但在androidios 设备上它工作正常。对于androidios 设备,它显示正确的计数。我想知道代码有问题吗?简而言之,上面的脚本每次都显示 +1(额外的 1 个视图)。 (仅适用于笔记本电脑或个人电脑)

【问题讨论】:

标签: php


【解决方案1】:
<?php

    // page-count.php - to be included in other files

    class hitcounter{
        private $file;
        private static $instance=false;
        
        private function __construct($file){
            $this->file=$file;
        }
        public static function initialise( $file ){
            if( !self::$instance ) self::$instance=new self( $file );
            return self::$instance;
        }
        public function write(){
            $i=$this->read();
            $i++;
            file_put_contents($this->file,$i,LOCK_EX);
        }
        public function read(){
            return file_exists($this->file) ? (int)file_get_contents($this->file) : 0;
        }
        public function display(){
            printf('<p>Page hits: %s</p>Filename: %s',$this->read(),$this->file);
        }
    }
    
    $file=sprintf('counter-%s.txt',ip2long($_SERVER['REMOTE_ADDR']));
    
    $oHit=hitcounter::initialise( $file );
?>

将更新文本文件的页面

<?php

    require 'page-count.php';
    # log the page view to the text file
    $oHit->write();
    
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Update & display hitcount</title>
    </head>
    <body>
        <h1>Update & View PageView count</h1>
        <a href='view-page-count.php'>View counter</a> | <a href='javascript:location.reload(true)'>Reload</a>
        <?php
            # display the hit count
            $oHit->display();
        ?>
    </body>
</html>

只查看结果的页面(view-page-count.php)

<?php
    require 'page-count.php';
    // do NOT log this page view - only display the count
?>
<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='utf-8' />
        <title>Display hitcount</title>
    </head>
    <body>
        <a href='javascript:history.go(-1)'>Previous Page</a>
        <h1>This page only VIEWS logfile - it does NOT update it.</h1>
        <?php
            $oHit->display();
        ?>
    </body>
</html>

【讨论】:

    【解决方案2】:

    正如其他人所说,在 PHP 中用一个简单的文件做一个计数器并不是一个好主意。网页上有许多您不知道的点击量(例如搜索引擎、已知和未知的蜘蛛、普通访问者……)。这些可能会或可能不会干扰并希望同时访问此文件。这会导致不清楚的情况,这可能会导致奇怪的错误。因此最重要的提示是使用能够在访问期间锁定数据并确保添加数据安全的数据库。

    让我们看看你的代码: 最大的问题之一是,写入文件意味着操作系统会清除文件并重写它。在最坏的情况下,这意味着硬盘启动,将自身定位在文件中,尝试打开它,清除它,向其中写入数据并随后关闭它。这将需要很多周期 - 足够的时间被其他尝试访问您的页面的人打断。当然,SSD 的工作速度要快得多,但不会发生数据冲突。

    如果您不能使用数据库,我们需要尝试“锁定”您的文件以供一次性使用。这是您的更新代码:

    $handle = fopen("counter.txt", "r");
    if(!$handle){
        echo "could not open the file" ;
    } else {
       $counter = (int ) fread($handle,20);
       fclose ($handle);
       $counter++;
    
       $handle = fopen("counter.txt", "w" );
       if (flock($handle, LOCK_EX | LOCK_NB)) {
           fwrite($handle, $counter) ;
           flock($handle, LOCK_UN);   // open the lock again
       }
       fclose ($handle) ;
    }
    

    这会尝试锁定您的文件。如果它不可锁定,它不会阻止进一步的执行,而是通过 fwrite-line。您可以删除 LOCK_NB 但这意味着您的服务器将等到块被提升,这可能需要一段时间。阻止网络服务器不是一个好主意,所以也许不计算访问者是更好的方法。

    第三个 - 稍微复杂一点 - 方法是在目录中为访问者编写唯一的文件,并自动收集(例如 cron-job)的选票,这些选票对访问者具有单一访问权限-文件。这样就不会发生碰撞。

    编码愉快。

    【讨论】:

    • 谢谢!我会检查的!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2017-12-12
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多