一、高级应用

1、计数器

计数器的原理很简单,只有两步:

第一步就是读写一个数字,第二步就是显示出来。一般CGI'大多直接写到文件系统,当然也可以利用MySQL来存储这个数字,完成第一步的操作。

第二步,除了直接写出数字之外,也可以用PHP的GD函数来试试。

(注:计数器一般都是以CGI程序做的,一般不会有人为了记这么一个数字建一个数据库,不过它很具有示范作用)

//方法1:读写文件系统Filesystem
<?
$arr = file("counter.txt");
$count = (int)$arr[];
$fp = fopen("counter.txt","w");
fputs($fp,++$count);
fclose($fp);
?>

这个程序要能够运行前:(勿忘修改两点)

第一要先建立一个counter.txt,里面含有一个数字0;

第二它忽略了应该对counter.txt做LOCK的操作。

//显示 这个数字
<? echo "您是第$count位访客"; ?>

高级显示:用PHP生成一个图形

//PHP 生成图形(5位数的计数器:00100)
<?
Header("Content-type:image/gif");
//...略去读入、更改count的部分
$im = ImageCreate(45,16);
$white = IMageColorAllocate($im,255,255,255);
$black = ImageColorAllocate($im,0,0,0);
imagefill($im,1,1,$black);
imagestring($im,5,0,0,sprintf("%05d",$count),$white);
imagegif($im);
imagedestroy($im);
?>

除了写到文件系统之外,还可以把到访次数,写到数据库的Table里,建立如下的数据库:

//方法二:写到数据库Database
mysql>creat table counter(
id int unsigned,
count int unsigned
);

用Id作为不同网站/页面的区分,而Count用于记录到访次数。那么一个Select命令:

select count from counter where id=3

就可以读出我们的Count值

update counter set count = count+1 where id=3

也能轻易地Update数值(注意:不是count = $count +1)

这个方法如果没有做LOCK,影响层面不大,最多显示的数字差几个,而count+1的操作不会Lost掉

使用数据库的好处是:对于每一个PHTML文件,都可以一个简单的Include操作,让这个Page的到访次数被统计(不一定显示)。

2、流量统计

流量统计是计数器的高级应用:世界上有许多软件可以帮助做流量统计的工作,大多使用HTTPD的Log文件(access.log)直接作分析,可以做到相当详尽而漂亮、清楚的图形显示,甚至会在适当的时候提醒一些信息。

这里介绍的是另外一种较简单的作法。对于“流量”,一般较感兴趣的,是使用者从什么地方联机进来?进来的时间?使用什么浏览器等信息。这些在PHP里,就是PHP的环境参数。如果在记录到访次数时,同时将这些参数记录下来,就可以用来统计。至于统计的结果,当然也可以用简单的图形来表示。

//第一步:建立Flow Table
mysql>create table flow(
id int unsigned,
accdate DATE,
acctime TIME,
browser varCHAR(30),
usrhost varCHAR(30)
);
//第二步:PHP记录日期、时间、浏览器信息以及使用者的Host Name等,Id一样是用来区隔不同的网站/网页的流量数据
<?
$str = "insert into flow values(3,CURRENT_DATE(),CURRENT_TIME(),'$HTTP_USER_AGENT,'$REMOTE_HOST')"
mysql_query($str,$link);
?>

第三步:读出数据,做一些简单的统计工作。比方说,想知道有多少人是从Hinet过来

select count(*) from flow where usrhost like '%hinet.net'

输出接口可以考虑用百分比长条图,直接一个ImageFilledRectangle(),就可以把算出来的一部分数据画成长条图了。、

3、留言板

利用数据库做留言板,最简单了。考虑一下需要的字段:姓名、张贴时间、Email、标题、内容、签名文件等。

第一步:建立一个数据库MSGboard(以及相关的Privileges),含有这么一个Table

mysql>create table board(
serial INT unsigned not null auto_inctement,
id INT unsigned not null,
postname CHAR(10),
postemail varCHAR(30),
posttime DATETIME,
subject var CHAR(40),
content tinyBLOB,
remarks varCHAR(255),
primary key(serial),
index(id)
);

特别的:我们使用一个Serial代表序号,Id来分别不同的留言板,另外加入了Index的概念,这样子在读取数据时会比较有效率。

第二步:写一个HTML接口让读者可以输入留言

<form antion="board.phtml" method="POST">
您的大名:<input type="Text" name="postname"><br>
您的信箱:<input type="Text" name="postemail"><br>
留言标题:<input type="Text" name="subject"><br>
留言内容:<textarea name="content" cols="20" rpws="4"
wrap="VIRTUAL"></textarea><br>
签名文字:<textarea name="remarks" cols="20" rows="2"
wrap=“VIRTUAL”></textarea><br>
<input type="Submit" name="" value="传送">
<input type="reset" vlue="重写">
</form>

第三步:在borad.phtml中,只要一行Insert命令,把数据写进去即可。至于读取留言,直接一次Select出来,然后显示出来就可以了。当然必要的美化画面是免不了的。

<?//php读取留言
$str = "select postname,postemail,
dateformat('y-m-d H:i',posttime),"
subject,content,remarks
form board
where id=3";
$result = mysql_query(...);
while(list($pname,$$pemail,$ptime,$subj,$content,$remk)=
mysql_fetch_row($result);
?>
姓名:<a href="mailto:"<?echo $pemail;?>"<?echo $pname;?></a><br>
留言时间:<?echo $ptime;?><br>
标题:<?echo $subj;?><br>
内容:<?echo $cotent;?><br>
签名:<?echo $remk;?><br><p>
<?
endwhile
?>

几个可议的地方:

  • 在“留言内容”里贴上HTML代码,会怎样?直觉的看法,应该在输出的时候,原来的HTML会发生作用,例如<fontsize="+3">...</font>会真的把字放大3级;然而,由于HTML里含有双引号(“”),会造成PHP对字符串的混淆。所以结果反而可能出现Error信息。解决这个问题的方法,在输入到数据库之前,先把所有的双引号等特殊字符Escape掉(在前面加上反斜线字符\),具体参考字符串函数addslashes()与quotemeta()。
  • 至于要不要开发使用者输入HTML代码,也是依个人喜好而定,原则上来说应该开放,不过万一读者的HTML代码不小心写错了,那么辛苦做好的格式可能会走样
  • 在Textarea里面,用户也许很自然的用ENTER换行,用TAB或数个空格来达到他要的效果。记录到数据库里,不过对应到(\n),(\t)与Space字符。于是在输出的时候,HTML代码真的会有换行、TAB与空格,但是用Browser看到却完全连在一起。所以,应该事先把这些字符换掉。例如:nl2br(),很轻松的处理完换行的问题。

4、公告栏(新闻发布)

把留言板稍微变化一下,可以做到另一种效果:公告栏,也有人叫它新闻系统。一进去会看到很多新闻标题(一两句话),点进去看全文。

延续上面留言板的结构,只要在Select上下功夫就可以了。

第一步:Show标题的页面

<?php
$str = "select serial,subject from board where id=3 order by posttime desc limit 10";
...
echo "<a href=\"show.phtml?$serial\">$subj</a>; ?>

这样会显示出标题,点一下会Link到show.phtml:

<?
$str = "select .. from board where id=3 and seria = $serial";
...
?>

第二步:做一个类似留言板的Web接口,也许用一下密码保护,让客户自己去找开他们的新闻,直接插入到数据库,这样下一个浏览器的Request,显示的新闻标题立刻更新了。(这样管理许多网站的WebMaster一定会很高兴!不用再因为客户的一通电话,就去修改一堆HTML代码了)

升级1.0:加上一些管理接口,开放让客户自己去修改/删除贴过的东西,也不是什么难事。把数据读进来,放进Form的Value值当作默认值,修改完的数据用Update送回数据库即可。

升级2.0    像是SeedNet或是一些证券公司的网站,常常有一些新闻或消息,不但显示出标题,还显示出大约100字的内容,然后一个More Information...链接到全文。基本上跟上面的结构没什么两样,只不过在要Show Subject时,同时显示出Content前面固定长度的字符串而已。

//显示出Content前面固定长度的字符串
<?
$str = "select serial,subject,left(content,100) from boar dwhere id=3 order by posttime desc limit 10";
...
echo "<a href=\"show.phtml?$serial\">More...</a>"
?>

5、讨论区

讨论区一般常见的有两种:

第一种像是Matt`s Script(http://www.worldwidemart.com/scripts/)使用的是全部展开标题的树状结构,一篇Follow的文章紧跟在原来的下面,优点是层次分明,一目了然,而且可以有好几层。

第二种原则上只有两层,首先像公告栏似的列出一堆标题,然后点进去就是所有的关于这个主题的文章。优点是速度快,管理与程序结构比较单纯。

这里重点以第二种快速的讨论区说明,然后等到抓到精髓之后,应该可以设计出更个性化、方便灵活的讨论区。第一种树状结构在数据库的角度没什么太大不同,不过显示的接口比较花功夫,可以自行试试看。

第一步:规划一下Table的结构。每篇文章(每笔数据)其实内容跟“留言”或“新闻”差不多,有主题、有内容、有发布者的姓名等。

  • 关键点在“Group”跟“Order”,就是说这些一篇一篇的文章,哪些是同一个主题下的讨论,其中先后次序又应该如何。
  • 另外,假设有20,000篇文章在数据库里,也许只分属2,000个主题,因此为了空间的考虑,应该把Subject取出来独立做一个Table。
create table subject(
subject_id INT unsigned not null auto_increment,
subject_name CHAR(20),
primary key(subject_id)
); creat table content(
content_id INT unsigned not null auto_increment,
subject_id INT unsigned not null,
post_order INT unsigned,
postname CHAR(10),
postemail CHAR(30),
...
primary key(content_id),
index(subject_id)
);
  • 现在我们用了两个Tables,其中Content已经不存在Subject数据,直接用一个subject_id join到Subject Table。另外设计一个post_order,用来记录该文章到底在同一个主题的第几篇。
  • 用户张贴新的主题时,要做两个Insert操作,一个到Subject Table,另一个到Content Table,用户对某个主题Follow讨论时,则只有Insert到Content Tabel。如过要同一主题所有新的文章一律放在最后面,那post_order只要最大的加一就行。如果要插入在Follow的文章后面,还得Update同一主题的所有post_order值。

看显示的Query会更清楚一些:

$str = "select subject_id,subject_name from subject";//列出所有Subject
...
echo "<a href=\"show.phtml?$subject_id\">$subject_name</a>;
$str = "select post_name,...from content
where subject_id = $subject_id
order by post_order";
...

上面的,只是原理而已,真的要运行,站在用户接口的角度,做到这样还太简单。可以多发挥想象力,例如结合后面的会员程序等,创造一个真正方便又快速的讨论区程序出来。

6、全文检索

坑:简单的想法,把所有的字放在数据库中,一搜寻就好了,问题是,第几页?第几行?怎么记录呢?总不能回答“找到”就可以把!

思路:把一整页当成一笔数据总行吧!这样可以知道找到的字符串是在第几页了。

还有问题:刚好在分页的地方的字符串怎么办?

思路:要设计全文检索,(认为)应该考虑的是,要做到什么程度。比方论文检索,也许找到哪一篇论文中有就可以了,而一本书的检索,至少应该到某一章节。

  • 两种方式:文件形式,数据库形式。
  • 可以自定义一种规则,读到某个特殊字符/字符串代表换行/换页等,然后把文件一行一行读进来。

    编号id

    章chapter 节section 段parag 内容content
    1 1 1 1 这是第一段,这是第一段,这是第一段
    1 1 1 2 这是第二段,这是第二段,这是第二段

参考:这样只要一个Select...Where ContentLike ‘%$key%’就可以了

7、会员

做一个Table记录会员数据,不是什么难事。困难的地方是,有了会员数据之后,那些要会员才能存取的网页,要如何保护?

坑:第一个直觉的想法,利用Apache本身的提供的登入限制功能就好了。通过.htaccess的设置,把这些网页放在一个目录下面,就可以达到这样的效果。

  • 第一个困扰:未来有新的用户,或者要更改密码时,都必须执行Htpasswd,要做到Web接口管理的话,可以用PHP写一个exec()做到。
  • 第二个困扰:如果会员数量庞大,速度会慢下来,当然也可以用Apache提供的DBM authentication解决。
  1. 因为Apache Authentication通过Header传送,PHP一样可以传送Header,因此可以利用这点,向Browser要求一个Aiuthentication,传回来Username跟Password自己到MySQL去做Check,不通过Apache。(注意:这个方法不要跟Apache本身的.htaccess一起用)
  2. 如下代码,读入Username和Password,配合MySQL的Member,后面就没问题了、如果在每一个需要保护的PHTML都加上这一段,就可以达到预期的效果,当然跟Apache Authentication一样,最好Realm都是同一个。
<?
if(!$PHP_AUTH_USER):
Header("WWW-authenticate:basic realm=\"会员登入\"");
Header("HTTP/1.0 401 Unauthorized");
//用户按了cancel的话
echo "很抱歉!您没有读取的权限!\n"
exit;
else:
echo "嗨! $PHP_AUTH_USER.<p>";
echo "您用的密码是 $PHP_AUTH_PW.<p>";
endif;
?>
  • 上述两种方式,基本对Browser端而言是一模一样,只是Server运行方式不同而已。换句话说,每一次Browser激活后,只要通过一次检查,对相同的Realm的Username/Password都会被保存下来,再次进去则不必输入用户名称与密码。这也是最大的缺点:没有Logout,除非关闭Browser。

正确的做法:一般网站多半采用另一种方式:Unique ID。

原理是:不管同一个时刻有多少人进来,对每个Login指定一个暂时的、唯一的ID,存在Cookie或者用参数传递。这样只要把Cookie删除,或者把Server端相对的ID删掉,就算Logout了。

问题:这个ID要用什么比较好?又不会重复?

解决:PHP提供一个函数Uniqueid(String Prefix),以微秒为基准产生一个字符串,加上Prefix可以长到一百多个字符。更安全的作法,则是利用随机数以及编码:

mt_srand((double)microtime()*1000000);
$id = des(uniqid(mt_rand(1,2000)));

这样会以1~2000的数字为Prefix,产生Unique ID,再经过编码加密,让Id成为一个长32个字符的“唯一”字符串。

当然,Member Table必须也要多一个字段了:

uid CHAR(32)

用这个Unique ID的方式,应该另外设计一个简单的Form,输入Username跟Password

<form action="login.phtml" method="POST">
名称:<input type="Text" name="username"><br>
密码:<input type="Text" name="userpass"><br>
<input type="Submit" name="" value="进入">
</form>

进来之后,检查Username/Password跟在数据库里的是否一样,一样的话,产生Unique ID,存到Cookie中,也记到Member Table的Uid里。之后的Select命令,只要一个where uid=$id,就可以找出是哪一位Member。

把上述的操作,放在一个PHTML文件里,然后所有需要被保护的PTHML(没错,只有PHTML文件)最前面加上一个Enclude就能达到预期的效果。

8、个人专属网页

现在许多网站,尤其是证券的站点,都已经提供专为个人设计的画面,比如你只想看财经消息,不想看国际新闻,那么你Login之后的首页,就只显示财经消息,每个会员都可以自行设置一些选项。

用PHP怎么做到?把上述Member Tabe多加一些字段,用来存储属性,Login之后把这些属性一并抓出来,像这样:

<?
if($show_news&1):
//001 代表显示财经信息
?> 财经信息:... <?
endif;
if($show_news&2):
//010 代表显示国际消息
?> 国际消息:... <?
endif;
?>

9、购物车

沿用Member的概念,当第一件产品加入购物车的时候,给它一个Unique ID,并且记录下来,结算的时候再把同样的Unique ID的所有产品列出来即可。

第一步:至少需要两个像这样的Tables

create table product(
product_id INT not null,
product_name..
...
); create table cart(
cart_id INT not null,
uid CHAR(32),
product_id INT,
primary key(cart_id),
index(uid)
);

记录的数据会如下表所示:

cart_id uid product_id
1 ijghgdfafgsd 158
2 ijghgdfafgsd 134
3 ijghgdfafgsd 241
4 ygbfdsjdghgf 63
5 ygbfdsjdghgf 123

第二步:在PHP中一次找出来该Unique ID对应的,被选择的产品数据。当然时常要用到的“清除购物车”或是“修改”甚至“数量”,对应到Cart Table就可以了。

$str = "select product.product_name,...
from product,cart
where product.product_id=cart.product_id
and cart.uid='$id'";

购物车的另一种写法:利用联机进来的IP、Domain以及Browser信息($REMOTE_ADDR、$REMOTE_HOST、$HTTP_USER_AGENT),来确认“一辆”购物车,而不用Unique ID。

这样做的好处:不用通过Cookie或者参数的传递,对于不支持或拒绝接受Cookie的用户,也不会发生兼容的问题。


注:转载请注明出处

【前端阅读】——《活用PHP、MySQL建构Web世界》摘记之高级应用的更多相关文章

  1. 【前端阅读】——《活用PHP、MySQL建构Web世界》摘记之设计技巧

    二.设计技巧 Programming的习惯因人而异,这里只提供一些经验,可以参考. 1.利用Include模块化你的程序代码 Include函数基本上说:就像是把另一个文件(HTML或者PHP程序)读 ...

  2. 【前端阅读】——《程序员思维修炼》摘记&读后感&思维导图

    前言:这是一本介绍如何用脑的书,并从思维的角度(以程序员为例),介绍如何从新手成为专家.作者带领着读者(我)共同经历一次有关认知科学.神经学.学习和行为理论的旅程,探索人类大脑令人 惊奇的工作的机制, ...

  3. web.py+html+mysql实现web端小系统的问题汇总

    利用web.py+html(bootstrap)+mysql实现了一个小型的设备管理系统,在这个过程中遇到很多问题,将问题及解决方案总结如下,有遇到类似问题的同学,希望可以帮到你们. 1.关于中文的编 ...

  4. 个人学期总结及Python+Flask+MysqL的web建设技术过程

    一个学期即将过去,我们也迎来了2018年.这个学期,首次接触了web网站开发建设,不仅是这门课程,还有另外一门用idea的gradle框架来制作网页. 很显然,用python语言的flask框架更加简 ...

  5. Python+Flask+MysqL的web建设技术过程

    一.前言(个人学期总结) 个人总结一下这学期对于Python+Flask+MysqL的web建设技术过程的学习体会,Flask小辣椒框架相对于其他框架而言,更加稳定,不会有莫名其妙的错误,容错性强,运 ...

  6. 零基础转行web前端,如何高效的去学习web前端

    web前端开发要学的知识内容涉及的会很宽泛,虽然说主要是HTML.CSS和JavaScript这些基础知识点,但学前端开发除了要学这些基础知识外,学员还要在这之上进行延伸和深入的去学,而且互联网时代不 ...

  7. Python+Flask+MysqL的web技术建站过程

    1.个人学期总结 时间过得飞快,转眼间2017年就要过去.这一年,我学习JSP和Python,哪一门都像一样新的东西,之前从来没有学习过. 这里我就用我学习过的Python和大家分享一下,我是怎么从一 ...

  8. openresty 前端开发入门五之Mysql篇

    openresty 前端开发入门五之Mysql篇 这章主要演示怎么通过lua连接mysql,并根据用户输入的name从mysql获取数据,并返回给用户 操作mysql主要用到了lua-resty-my ...

  9. virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续)

    virtualbox搭建ubuntu server nginx+mysql+tomcat web服务器1 (未完待续) 第一次接触到 linux,不知道linux的确很强大,然后用virtualbox ...

随机推荐

  1. MFC之HTTP文件上传

    BOOL UploadFile(LPCTSTR strURL, LPCTSTR strLocalFileName) { // 如果URL为空或者文件不存在,直接返回 if (strURL == NUL ...

  2. POJ 3368:Frequent values(线段树区间合并)

    题目大意,给出一段非降序列,求一些区间中出现频率最高的数的出现次数. 分析: 显然,区间中一个数多次出现必然是连续的,也就是最长的连续相等的一段. 用线段树解决,维护三个信息:一个区间最长连续的区间的 ...

  3. HDU 5289 Assignment(二分+RMQ-ST)

    Assignment Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total ...

  4. POJ1848 Tree 【树形dp】

    题目链接 POJ1848 题解 由题,一个环至少由三个点组成,一个点作为根时,可以单独成链,可以与其一个儿子成链,或者与其两个儿子成环,与其一个剩余链长度大于等于2的儿子成环. 那么我们设最小代价 \ ...

  5. codechef May Challenge 2016 CHSC: Che and ig Soccer dfs处理

    Description All submissions for this problem are available. Read problems statements in Mandarin Chi ...

  6. bzoj 3704 昊昊的机油之GRST 贪心dp,思维

    昊昊的机油之GRST Time Limit: 10 Sec  Memory Limit: 1024 MBSubmit: 80  Solved: 33[Submit][Status][Discuss] ...

  7. BZOJ 3640: JC的小苹果

    3640: JC的小苹果 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 425  Solved: 155[Submit][Status][Discus ...

  8. socket介绍(webService适用场景)

    1.使用场景         - 不同的移动客户端访问      - 需要访问第三方的项目 2.访问第三方应用的方式      ISO的七层模型  : 物理层.数据链路层.网络层.传输层.表示层.会话 ...

  9. 【CDockablePane】关于CDockablePane

    1.DockPane是CFrameWndEx框架窗口的函数,不能用于基于对话框的应用程序,也不能用于老版本VC,只能用于基于单文档和多文档的应用程序. 2.最佳变通实现办法:创建CFormView基类 ...

  10. linux下终端录制

    主要是以下三步: 一.安装软件:curl -sL https://asciinema.org/install | sh 二.录制终端:asciinema rec filename 三.回放终端:asc ...