增强版的计数器

增强版的计数器

//文章来源:PHP 4.X 与电子商务网站开发实战
//整理:dx_andy
//时间:2007.8.17 早
//测试环境:win32 apache2.2.4 php5.2.1 mysql5.0.27
//联系:QQ:45665758 E-mail:[email protected]

        现在流行于互联网上的计数器程序(PHP)一般都很简单,相对来说功能上也相对较少。比如说它只能提供单个的页面使用,对于某些较大的网站来说,还要统计每个专栏的访问量,而不仅仅是首页的访问量。其次,该计数器作弊也很简单,只要不停的刷新,访问量就会不停地向上涨。对一个网站来说,这样是很过分的。
        那么,我们应该怎样来改进它呢?
        第一方面,我们可以在count数据库中加入一项id,作为记录每个专栏的代号,每一个id对应着一个计数值count。在不同的专栏访问时,只要指定不同的id就行了。对于第二项,可以考虑另建一个辅助的数据表,记录登录者的ip、访问的栏目和上次访问时间time。每当一个访问者访问该栏目时,从数据库里选择其ip和id共同对应的上次访问时间,如果数据库里不存在该ip和id,可以认为这是一个新用户,计数可以加1,如果存在,则比较当与当前时间和上次访问时间。两者之差大于1小时,则计数也可以加1。最后删除数据表中时间与当前时间相差大于1小时的项(这一点是为了防止数据表过于庞大)。
        具体看一看实现的方法。
        怎样获得访问者的ip?这需要用到一个函数getenv(),其定义为
        string getenv(string varname)
        其作用是返回环境变量的值,varname是环境变量名。REMOTE_ADDR表示访问者的IP地址。所以用$ipaddress=getenv("REMOTE_ADDR")就可以得到访问者的IP地址。
        对时间,可使用time() 函数,以取得系统的UNIX 时间,以秒做单位。一小时的差别可以用3600秒来代替。
        让我们来看一看实际的操作过程,假定有三个栏目(即建立3个id)。
        建立数据库:
        create table encount
        (
        count int not null,
        id int not null
        );
       
        insert into encount values(0,0),(0,1),(0,2);        //在encount表中插入三个数据
       
        create table ipandtime
        (
        ip varchar(15),
        id int not null,
        etime int not null
        );

<?php
        //增强版的网页计数器
        //文件名:enhancecount.php
        //代码来源:PHP 4.X 与电子商务网站开发实战
        //整理:dx_andy
        //时间:2007.8.17 早
        //此代码在win32 Apache2.24 PHP5.5.1 MySQL5.0.27环境下测试通过

        function enhancecount($id)
        {
                $ipaddress=getenv("REMOTE_ADDR");
               
                //echo "\$ipaddress=".$ipaddress."<br>\n";
               
                $currenttime=time();
               
                //echo "\$currenttime=".$currenttime."<br>\n";
               
                $link=mysql_connect("localhost","root","123") or die("Unable to conn MySQL!");
                mysql_select_db("test") or die("Unable to select DB!");
                $query="select etime from ipandtime where ip='$ipaddress' and id='$id'";
                $result=mysql_query($query);

                //if($result) echo "select etime OK!<br>\n";

                if($row=mysql_fetch_row($result))
                //如果返回值存在,则执行下面语句。
                {
                        $timestamp=$row[0];
                       
                        //echo "\$timestamp=".$timestamp."<br>\n";
                        //echo "\$currenttime-\$timestamp=".($currenttime-$timestamp)."<br>\n";

                        if($currenttime-$timestamp>3600)
                        //如果时间超过1个小时,则更新。
                        {
                                $query="update ipandtime set etime='$currenttime' where ip='$ipaddress'";
                                mysql_query($query);
                                $query="delete from ipandtime where etime<('$currenttime'-3600)";
                                mysql_query($query);
                                $update=1;
                                $count=updatecount($id,$update);
                                mysql_close($link);
                                return($count);
                                exit();
                        }
                        //如果小于1小时,只执行删除大于一小时的表项的命令。
                                $query="delete from ipandtime where etime<('$currenttime'-3600)";
                                $dele=mysql_query($query);
                               
                                //if($dele) echo "Small Delete ipandtime is OK!<br>\n";

                                $update=0;
                                $count=updatecount($id,$update);
                                mysql_close($link);
                                return($count);
                                exit();
                }
                //如果不存在,更新数据,并将该ip插入数据库。
                        $query="insert into ipandtime(ip,id,etime) values('$ipaddress','$id','$currenttime')";
                        mysql_query($query);
                        $query="delete from ipandtime where etime<('$currenttime'-3600)";
                        mysql_query($query);
                        $update=1;
                        $count=updatecount($id,$update);
                        return($count);
        }
       
//更新数据库encount的函数,形参为id和布尔量update

function updatecount($id,$update)
{       
        // echo "function updatecount \$id=".$id." \$update=".$update."<br>\n";

        $query="select count from encount where id='$id'";
        $result=mysql_query($query);
        $answer=mysql_fetch_row($result);
        $count=$answer[0];
        if($update)
        {
                $count++;
                $query="update encount set count='$count' where id='$id'";
                mysql_query($query);
        }
        return($count);
}

?>

        上面的函数enhancecount()的返回值为$count,只要在其他需要使用的文件里调用就行了。
        比如,假设某一需要调用该文件的栏目的id为2,那么只要用如下语句就可以达到调用它的目的。

        <?php
        require('enhancecount.php');
        $count=enhancecount(2);
        echo "您好,您是第$count位访问者!";
        ?>

        对由上面的程序稍加改动,就可以实现每日的访问量计数和总访问量计数,当然,数据库也需要用相应的扩充和修改,这一点请读者自已完成。

[ 本帖最后由 dx_andy 于 2007-8-22 14:18 编辑 ]

牛,呵呵,狂顶下!