文章教程

3.2图形化访问计数器

9/17/2020 9:43:31 PM 人评论 次浏览

3.2 图形化访问计数器

恐怕很多读者有在画面上放置访问计数器的经验吧。追溯到网络技术的CGI时代,页面计数器可是典型的应用之一了。

本节利用上一节“记录每页的浏览数”中使用的access_counter表里的记录,开发出了页面使用的图形化访问计数器,如下图所示。

alt

本例要点

access_counter表里管理的都是些数字,本节的关键是将这些数字转换成图片(<img>)后,再在画面显示出来。

当然可以将每一个统计数据都做成图片,但是统计数据在不断增加,这几乎是不可能的工作。本节准备了0到9的10个图片,对画面上统计数据,一数字对应一个数字图片的形式来进行显示。

请大家注意下面的程序中,在从access_counter表里取得访问统计数据后,对数据进行的单字节数字分解的逻辑。

目录结构

alt

数据库的表结构

alt

代码

alt

将计数统计用的脚本CounterUp.php,显示计数的脚本包含过来。

alt

showCounter函数唯一接受的参数为数字图片的文件名的固定部分,提供pic0.gif到pic9.gif的图片时,为pic。不传入参数的情况下,默认为pic。

alt

连接数据库,与3.1节中的内容相同。

alt

当前的URL为条件对表access_counter进行检索。

alt

fetch函数返回False时,计数刚开始,因此统计变量$num赋值为1。

alt

strlen函数求出统计数据的字节数,并作为循环的上限。16行到19行循环进行统计数据的字节分解。

例如统计数字为5432时,从最初的循环到结束的结果如下。

alt

返回值保存在变量$val,最后将变量转换为对应的图片,显示在画面上。

alt

补充

prepare方法的有效性

3.1节、3.2节中介绍了应用prepare方法进行“SQL命令准备”的概念。进行SQL命令准备有以下两重意义:

(1)性能提高

通常在程序内部,执行普通的SQL语句时,要经过“解析→编译→执行”等阶段。使用prepare方法后,事先对SQL命令进行“解析→编译”的处理,将状态保存起来,执行时,直接进行最后一步“执行”就可以了。

这样,要改变条件多次执行SQL命令时,前面的“解析→编译”两个步骤就可以省略了,能提高程序处理的性能。

(2)避免SQL注入脆弱性

SQL注入(injection)脆弱性是指通常在应用数据库的系统中,执行SQL命令时,由于疏忽对用户输入的条件数据进行相关检查,而出现的安全漏洞。

例如,需要根据输入的条件对表user进行检索,服务器端的程序中有如下的动态SQL命令:

alt

其中变量$id由终端用户输入,如果检查存在漏洞,而用户输入的不是普通字符,而是如“hell’;UPDATE user WHERE set name =‘AAAA’”样的字符串,会出现什么样的后果呢,我们看看下面的SQL命令。

alt

这样,用户就可以对数据进行严重地破坏了,这是非常严重的安全漏洞。

但是,如果使用了prepare方法(严格地说是执行SQL的excute方法)。在设置预留置换位(place holder)时,已经自动进行引号转换了,即将所有单引号转换为双引号。这样一来,用户输入的内容只能作为一个字符看待,再也不出现SQL注入脆弱性的问题了。

可以使用quote函数实现单双引号转换,但是如果自己事先进行转换时,不小心总会出现疏漏,怎么说也挺麻烦。因此在没有什么特殊理由的情况下,动态地生成SQL命令时请务必使用prepare函数。

无名参数与有名参数

在prepare方法中使用预留置换位时,可以使用无名参数与有名参数两种形式,分别如下。

无名参数:

alt

有名参数:

alt

无名参数以[?],有名参数以[:参数名]嵌入在SQL中,这两种形式都用bindValue进行实际数值的设定,不同的是,有名参数时第一参数直接使用名称,无名参数时使用序号(从1开始),形式如下:

alt

无名参数与有名参数都可以使用,基本上没什么区别。两者分别有如表3-3所示的优点与缺点。

表3-3 无名参数与有名参数的优缺点

alt

本书优先重视程序的可读性(即参数的易理解性),除了一部分例外,都使用有名参数的方式。

参数的默认值

本节做成的showCounter函数中使用了带默认值的参数的形式,如下:

alt

带默认值的参数可以省略,但是在使用带默认值的参数时,该参数必须放在其他参数之后,如果像下面所示的方式定义函数时,如果省略时,将会得意想不到的结果。

alt

只有采用如下的方式的定义,才能省略带默认值的参数:

alt

是否可以用字符串分解函数split。

在Perl等程序中可以使用split函数将字符串分解为一个一个字节,那么在PHP是否也可以使用split进行类似的操作呢?下面是验证代码。

alt

结论是,分解失败。Perl的情况下以空字符为间隔可以分割出字节为单位的字符,而在PHP中split函数则返回错误。

教程类别