3.4 构筑简单的网络调查程序系统
大家在新浪、网易等网站上经常会看到网上调查,并且能够适时地看得到调查结果。本节将会应用PHP技术构造一个简单的网络调查程序。说它简单,其实其外观已经和新浪等网站的网络调查没有什么区别了,你甚至直接可以拿去用在你自己的网站上。
关键是,健全的网络调查程序还应该有一些防作弊的手段,也就是应该对参加调查的个体进行一些公正的检查(check),比如显然不能允许同一个用户进行反复的投票等。这些都超出了本书的范围,有兴趣的朋友,可以琢磨琢磨。
本例要点
构筑网络调查程序的第一步是,设计程序所要用到的表格,首先可以想到的,肯定需要一个保存调查结果的表,一个调查选项对应一条记录,记录中有保存投票数的列。本节的目标是构筑一个调查系统,既然是系统,那就不是只能进行一种网络调查了,应该可以进行多种网络调查,因此应该有一个保存所有类型网路调查信息的表。
上述的这些思考过程,实际上就是在做数据库设计,随着分析,我们就可以找到构筑系统所需的表,最后完成关系数据库的(RDB)的设计。在复杂的系统中,在初步整理出来的表的基础,还要进行满足关系数据库定义的规范化动作,本节最后的补充材料里会有进一步的阐述。
目录结构
数据库的表结构
表3-5 调查设问信息(quest_master)
表3-6 调查结果信息(quest_answer)
本例代码
在内嵌帧中调用网络调查表单,根据给调查ID(qid)赋不同的值来调用相应的调查表单。
Browser是本节设定的“使用浏览器”的调查表单id。
根据调查ID(qid)搜索调查设问信息。指定qid不存在的情况时,显示错误信息并退出处理。
上面13行中的PDO::FETCH_ASSOC的作用是设置取出数据的模式,即取出的记录将以什么样的变量形式呈现。PDO::FETCH_ASSOC表示以联想数组的形式取出记录。下面就可以以$row[列名]的形式取得具体的数值:
继续搜索quest_answer表中的具体的调查设置选项。
18行到20行根据取得的调查设置选项来生成一系列单选按钮。
当fetch方法不能取得下一个记录时,会返回False,同时会终止while循环。
此处加入一个防止多重投票的检查。
利用Cookie设定值来判断用户是否投票,当然如果用户删除了Cookie,就可以进行连续投票了,因此这种检查也只能部分防止用户进行多重投票。
具体的检查以调查ID为键的Cookie是否设定,如果已设定,显示错误信息,5秒后跳转到ShowQuest.php。
对以指定调查ID、选项ID为条件的记录的投票数加1。
更新结束后,设定以调查ID为键的Cookie值,有效期限365天。
跳转到ShowQuest.php。
以指定的调查ID为条件检索调查设问以及投票状况,检索失败时,与ShowQuest.php中的处理相同,显示错误信息,并中断处理。
这里根据从表quest_answer中取得的投票数,决定图像的宽度,从而创造出类似于竖线类比图的效果。
补充
关系数据库的表的规范化
在关系数据库中排出数据的冗余,从而减少数据修改时的影响范围,对提高数据的独立性,防止更新时出现矛盾来说,具有重要意义,也是个重要的课题。
假设现实中存在如表3-7所示的数据。
表3-7 数据
粗略浏览一下数据,可以发现如下问题:
● 作者的列中有含有多个作者的情况
一列中含有多个数据时,意味着不能直接检索该数据了。比如要检索“李刚”这人所著的书,就会不仅仅出现“李刚”一个人所著的,还会出现“李刚~”,以及“~李刚”和“~李刚~”等数据,显著地降低了表的可搜索性及其性能。
● 无用数据多
书籍表中,存在“出版社”、“出版社注册资金”、“出版社设立日期”等内容,这些本来都是与出版社的相关内容,例如如果改动出版社注册资金时,所有与该出版社相关的数据都得修改。
修改后的结果如表3-8~表3-10所示。
表3-8 数据
表3-9 数据
表3-10 数据
表3-11 数据
这样就排除了数据的冗余。
进过了上述的表正规化处理,比如要检索“李刚”这人所著的书,就可以直接检索。另外,如果想增加作者的相关信息,只用修改作者那一个表,再增加数据就够了。
在上面的例子中,对表进行了详细的分解,实际数据库操作时必须再对表进行结合。结合的表越多,检索性能将越低,另外,构筑检索SQL时也会变得越来越复杂了。前一个问题,随着电脑性能的提高,采用高性能的硬件能解决检索性能下降的问题,后一个问题,如果必须将数据库提供给技术水平不太高的开发者使用时,会有许多隐含的风险。
从这个角度上说,并不是将表分解得越细越好,在实际的数据库设计时掌握好,分解的平衡也是一种很重要的能力。
知识专栏:性能调试的小技巧(四)——索引的例外情况
在“性能调试的小技巧(三)”中已经介绍过,使用索引后能提高数据库检索的反应速度。但是编写检索SQL时,并不能保证就一定能用上索引,需要引起注意。例如像如下的条件时,就没有使用上索引。
(1)使用<>,IS[NOT]NULL,LIKE等运算符时(但是,除了用LINK进行的前方一致的检索)。
(2)对索引列进行运算时。
(3)复合索引(多个列),而且WHERE语句里没有包含索引的第一列时。
碰到第1种情况时,应该检讨能不能用前方一致,“=”等运算符代替。第2种情况下,有时可以通过对运算式移项,将运算集中在右边对应这种情况(如VAL+10<100变为VAL<100-10)。在第3种情况下,只有通过修改复合索引来对应了。
共有条评论 网友评论