Ajax 和 XML: 使用 Ajax 实现打分评级和添加评论功能
来源:互联网 发布:网络教育大专本科 编辑:程序博客网 时间:2024/06/04 19:57
在由人员驱动的 Web 时代,允许读者评级和评论站点内容的功能是必不可少的。通过本文探索如何使用 Ajax 在站点中加入评级和评论功能。
我们大家都喜欢 评定内容的等级。我认为这是人类与生俱来的秉性。我和我的女儿都喜欢去电影院看电影;虽然她过去对电影的内容毫不讲究,不过现在却挑剔了许多,因为她已经 四岁了。我曾经教过她使用 “大拇指朝上” 和 “大拇指朝下” 的评级系统 à la Ebert 和 Roeper。(她曾经为 Shrek the Third 这部电影竖起了大拇指。)我认为这就是人们乐于在因特网上评论产品和文章的原因所在。
本文将介绍如何结合使用 MySQL、PHP、Prototype.js 和 Asynchronous Javascrīpt™ and XML (Ajax) 在站点中添加简单的评级和评论功能。
评级系统
虽然我女儿乐于使用大拇指进行评级,不过大多数人更倾向于另一种略有差别的评级系统:五星级评级系统,其中一颗星为最差,三颗星为中等。在本例中,我将使用五星级评级系统对电影进行评级。您也可以将本文中评级系统应用于需要的内容 — 如文章、产品和播客。
清单 1 显示了本例所使用的模式,其中创建了一个初始的 movies 表。这相当简单:在表中定义一个自动递增的电影 ID 和电影名称。然后,创建一个 rating 表保存电影的投票结果。这个表通过 movie_id
与 movie 表绑定在一起,表中还包含一个 rating 字段,取值范围为 1 到 5。
清单 1. rating.sql
DROP TABLE IF EXISTS movies;
CREATE TABLE movies (
movie_id INTEGER NOT NULL AUTO_INCREMENT,
name VARCHAR( 128 ) NOT NULL,
PRIMARY KEY ( movie_id )
);
DROP TABLE IF EXISTS ratings;
CREATE TABLE ratings (
movie_id INTEGER NOT NULL,
rating INTEGER NOT NULL
);
如果要执行 “一人一投” 的模式,则必须在 ratings 表中添加一个用户 ID,从而确保每个人只能对一部电影评定一次。考虑到程序的简单性,我并没有实现这一功能。
要将模式导入数据库,必须先创建一个数据库,然后再添加模式。可以使用以下命令行指令完成这些操作:
% mysqladmin create comments
% mysql comments < ratings.sql
您可能需要根据您的 MySQL 安装添加登录凭证。
完成这些步骤之后,我们需要使用一个页面显示可用的电影,并为每部电影添加一个评级页面链接。清单 2 显示了这个索引页面。
清单 2. index.php
<html>
<body>
<?php
require_once("DB.php");
$db =& DB::Connect( 'mysql://root@localhost/comments', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
$res = $db->query( 'SELECT * FROM movies' );
while( $res->fetchInto( $row ) )
{
?>
<a href="rate.php?id=<?php echo($row[0]) ?>"><?php echo($row[1]) ?></a><br/>
<?php
}
?>
</body>
</html>
简单起见,我使用结构化查询语句(Structured Query Language,SQL)语句在 movies 表中加入了一些著名的电影。下载 部分提供了示例代码。您可以在索引页面中看到这些电影,如 图 1 所示。
图 1. 电影列表
如果您无法通过示例代码显示出这个清单,可能您的机器未使用 PEAR 存储库安装 DB 模块。要安装它,只需在命令行中运行以下命令:
% pear install DB
现在,电影列表可以正常显示了。接下来,我们将实现电影评级页面,这个页面还可以显示当前投票的总排名和日平均排名。实现这些功能的 rate.php 页面代码如 清单 3 所示。
清单 3. rate.php
<?php
require_once("DB.php");
$db =& DB::Connect( 'mysql://root@localhost/comments', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
$id = $_GET['id'];
$title = '';
$res = $db->query( 'SELECT name FROM movies WHERE movie_id=?', array( $id ) );
while( $res->fetchInto( $row ) ) { $title = $row[0]; }
?>
<html>
<head>
<title><?php echo($title); ?></title>
<scrīpt src="prototype.js"></scrīpt>
<scrīpt>
function rate( value ) {
new Ajax.Updater( 'rating', 'ratemovie.php?id=<?php echo($id)?>&v='+value );
}
</scrīpt>
</head>
<body>
<h1><?php echo($title); ?></h1>
<div id="rating">
<img src="star_off.gif" ōnclick="rate(1)"></img>
<img src="star_off.gif" ōnclick="rate(2)"></img>
<img src="star_off.gif" ōnclick="rate(3)"></img>
<img src="star_off.gif" ōnclick="rate(4)"></img>
<img src="star_off.gif" ōnclick="rate(5)"></img>
<br/><br/>
<?php
$res2 = $db->query(
'SELECT count( rating ), sum(rating ) FROM ratings WHERE movie_id=?',
$id
);
while( $res2->fetchInto( $row ) )
{
?>
Votes: <?php echo($row[0]); ?><br/>
Average Rating: <?php echo($row[1]/$row[0]); ?>
<?php
}
?>
</div>
</body>
</html>
文件顶部的代码通过传递 ID 参数获得电影标题。在脚本中间部分,我们导入了 prototype.js 库并创建了一个 rate()
Javascrīpt 函数,这个函数将通过 Ajax 使用 Prototype 库调用 ratemovie.php 页面。然后,我们添加了一组星形图像,点击这些图像时脚本将调用 rate()
函数。
在文件底部的代码中,我们运行了一个快速查询获取投票数和指定电影的投票总数。然后,在页面中显示出这些数据,这样读者就可以知道该电影的评级情况。
清单 4 中的 ratemovie.php 脚本负责在数据库中添加评级,然后返回一些超文本标志语言(Hypertext Markup Language,HTML)代码,以替换原始页面中的投票星级和评论数。
清单 4. ratemovie.php
<?php
require_once("DB.php");
$db =& DB::Connect( 'mysql://root@localhost/comments', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
$v = $_GET['v'];
$id = $_GET['id'];
$sth = $db->prepare( 'INSERT INTO ratings VALUES ( ?,? )' );
$db->execute( $sth, array( $id, $v ) );
?>
<img src="star_<?php echo( ($v>0)?'on':'off' ) ?>.gif"></img>
<img src="star_<?php echo( ($v>1)?'on':'off' ) ?>.gif"></img>
<img src="star_<?php echo( ($v>2)?'on':'off' ) ?>.gif"></img>
<img src="star_<?php echo( ($v>3)?'on':'off' ) ?>.gif"></img>
<img src="star_<?php echo( ($v>4)?'on':'off' ) ?>.gif"></img>
<br/><br/>
<?php
$res2 = $db->query(
'SELECT count( rating ), sum(rating ) FROM ratings WHERE movie_id=?',
$id
);
while( $res2->fetchInto( $row ) )
{
?>
Votes: <?php echo($row[0]); ?><br/>
Average Rating: <?php echo($row[1]/$row[0]); ?>
<?php
}
?>
图 2 显示了运行中的评级页面。
图 2. 评级页面
单击页面的中星形图案时,投票将添加到数据库中;星形图案、投票和平均评级的 HTML 代码会发生改变,从而反映出投票已添加。
理想情况下,我希望能够在主页上看到所有电影的评分情况。清单 5 中的新版索引页面实现了这一功能。
清单 5. index2.php
<html>
<body>
<table>
<?php
require_once("DB.php");
$db =& DB::Connect( 'mysql://root@localhost/comments', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
$res = $db->query( 'SELECT * FROM movies' );
while( $res->fetchInto( $row ) )
{
$res2 = $db->query(
'SELECT count( rating ), sum(rating ) FROM ratings WHERE movie_id=?', $row[0]
);
$rating = 0.0;
while( $res2->fetchInto( $row2 ) ) { $rating = $row2[1] / $row2[0]; }
?>
<tr><td align="center">
<?php echo( $rating > 0 ? $rating : 0 ) ?>
<td><td>
<a href="rate2.php?id=<?php echo($row[0]) ?>"><?php echo($row[1]) ?></a>
</td></tr>
<?php
}
?>
</table>
</body>
</html>
从 图 3 中可以看出,各个电影的评级情况都在新版的索引页面中显示出来了。
图 3. 更新后的电影页面
使用 Ajax、PHP、MySQL 和非常方便的 Prototype.js Javascrīpt 库实现投票模式就这么简单。
在下一个示例中,我们将实现电影评论功能。
评论
Web 上的评论系统形式各异,从极其简单的博客评论系统(可以对博客条目发表一连串的评论)到异常复杂的主题评论系统(比如 Slashdot 上的评论系统),不一而足。
本例所使用的评论系统比较简单。您可以根据需要对它进行适当的调整。
首先,在已有数据库模式中添加一个表,如 清单 6 所示。
清单 6. comments.sql
DROP TABLE IF EXISTS comments;
CREATE TABLE comments (
movie_id INTEGER NOT NULL,
email VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
comment TEXT NOT NULL
);
所添加的是 comments 表,这个表通过 movie_id
字段与电影关联在一起。表中定义了一个电子邮件地址、评论者名称和评论文本。这是一个相当基本的评论系统,类似于 WordPress 和 MoveableType 博客软件上的评论系统。
如果想要创建一个主题评论系统,则需要在表中添加一个自动递增的 ID 字段,然后使用一个可为空的 parent_id
字段指向各个评论的父级评论。如果该 字段为空,则这个评论是顶层评论。
要在评级页面中加入评论功能,我们需要在页面底部包含一些额外的脚本。清单 7 显示了这个新的 php 代码。
清单 7. rate2.php
...
<h2>Comments</h2>
<div id="comments">
<?php
$res3 = $db->query(
'SELECT * FROM comments WHERE movie_id=?',
$id
);
while( $res3->fetchInto( $row3 ) )
{
?>
<div>
<a href="mailto:<?php echo($row3[1]) ?>"><?php echo($row3[2]) ?></a> says:
'<?php echo($row3[3]) ?>'
</div>
<?php
}
?>
</div>
<div style="margin-top:20px;">Add your own comment:</div>
<form id="cform">
<input type="hidden" name="id" value="<?php echo($id)?>">
<table>
<tr><td>Name:</td><td><input type="text" name="name"></td></tr>
<tr><td>Email:</td><td><input type="text" name="email"></td></tr>
<tr><td>Comment:</td><td><textarea name="comment" id="comment_text"></textarea></td></tr>
</table>
</form>
<button ōnclick="addcomment()">Add Comment</button>
<scrīpt>
function addcomment()
{
new Ajax.Updater( 'comments', 'addcomment.php',
{
method: 'post',
parameters: $('cform').serialize(),
onSuccess: function() {
$('comment_text').value = '';
}
} );
}
</scrīpt>
</body>
</html>
脚本首先使用数据库中关于该电影的评论填充 “comments” <div>
标记。 然后,在标准 HTML <form>
标记中包含评论名称、评论者电子邮件和评论内容的字段。form 标记中还包含一个隐藏值(当前所查看电影的 ID),从而评论添加脚本知道应该将这个评论指派给哪部电影。
表单下面的 Add Comment 按钮将调用 addcomment()
Javascrīpt 函数。这个函数使用了 Prototype.js 库中的 Ajax.Updater
对象来调用 addcomment.php 脚本。它使用了非常方便的 serialize()
函数对名称、电子邮件地址和评论内容进行打包,这个函数也是由 Prototype.js 提供的。
如果评论成功,代码会重置评论字段的文本,这样可以允许用户随意添加任意数量的评论,而不用重新输入名称和电子邮件地址。
清单 8 显示了 addcomment.php 脚本。
清单 8. addcomment.php
<?php
require_once("DB.php");
$id = $_POST['id'];
$db =& DB::Connect( 'mysql://root@localhost/comments', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
$sth = $db->prepare( 'INSERT INTO comments VALUES ( ?, ?, ?, ? )' );
$db->execute( $sth, array( $id,
$_POST['email'], $_POST['name'], $_POST['comment' ] ) );
$res = $db->query('SELECT * FROM comments WHERE movie_id=?', $id );
while( $res->fetchInto( $row ) )
{
?>
<div>
<a href="mailto:<?php echo($row[1]) ?>"><?php echo($row[2]) ?></a> says:
'<?php echo($row[3]) ?>'
</div>
<?php
}
?>
首先,脚本将 POST 数据中指定的评论内容添加到数据库中。然后,将所有的评论内容作为 HTML 代码输出,其方式与原始评级页面一样,只不过这次页面中额外显示了用户所提供的评论。
新的评级页面如 图 4 所示。
图 4. 更新后的评级页面,具有评论功能。
这个评论系统可以即时地向用户反馈信息。用户单击 Add Comment 时,页面会立即更新评论内容。系统还可以显示出其他用户在这期间提交的评论。
您可能需要扩展这个示例,使服务器可以自动更新评论部分。当然,您大可不必调用 addcomment.php 来完成这点。可以使用另一个脚本来返回评论,而不必添加新脚本。为此,Prototype.js 提供了一个 Ajax.PeriodicalUpdater
类,使用这个类中定义的 ID、刷新率和 URL 可以根据需要刷新 Web 页面中的任何部分。
添加 RSS 提要
扩展该示例的另一种简单的方法是将电影列表的内容和排名作为 RSS 导出。实现这一功能的代码如 清单 9 所示。
清单 9. rss.php
<?php
header( "content-type:text/xml" );
?>
<rss version="0.91">
<channel>
<title>Movie rankings</title>
<link>http://localhost/comments/rss.php</link>
<?php
require_once("DB.php");
$db =& DB::Connect( 'mysql://root@localhost/comments', array() );
if (PEAR::isError($db)) { die($db->getMessage()); }
$res = $db->query( 'SELECT * FROM movies' );
while( $res->fetchInto( $row ) )
{
$res2 = $db->query(
'SELECT count( rating ), sum(rating ) FROM ratings WHERE movie_id=?', $row[0]
);
$rating = 0.0;
while( $res2->fetchInto( $row2 ) ) { if ( $row2[0] > 0 ) $rating = $row2[1] / $row2[0]; }
?>
<item>
<title><?php echo($row[1]) ?> -
<?php echo( $rating > 0 ? $rating : 0 ) ?> stars</title>
<link>http://localhost/commentsts/rate2.php?id=<?php echo($row[0]) ?></link>
<descrīption><?php echo($row[1]) ?></descrīption>
</item>
<?php
}
?>
</channel>
</rss>
清单 9 中的代码的作用类似于使用 HTML 格式导出数据。它使用 <title>
、<descrīption>
和 <link>
标记指向各个电影页面,而不是 HTML 中的 <table>
、<tr>
和 <td>
标记。当我在 Firefox 浏览器中打开这个页面时,所显示的页面如 图 5 所示。
图 5. 浏览器中的 RSS 提要
很容易吧!从 php 中获取 XML 提要就是这么简单。
当我使用以下命令行在本地运行代码时:
% php rss.php
我可以直接看到 RSS XML。清单 10 显示了这个 RSS 的一部分。
清单 10. RSS excerpt
<rss version="0.91">
<channel>
<title>Movie rankings</title>
<link>http://localhost/comments/rss.php</link>
<item>
<title>Star Wars - 4.5 stars</title>
<link>http://localhost/commentsts/rate2.php?id=1</link>
<descrīption>Star Wars</descrīption>
</item>
<item>
...
结束语
最近,关于用户生成内容的话题格外引人关注,尤其是它如何增强 Web 2.0 的力量这方面。与本文中示例一样,您可以使用 Prototype.js 库之类的优秀工具轻易地构建 Ajax 应用程序。对网站内容的评级和评论功能确实是一种极好的用户生成内容的形式。
- Ajax 和 XML: 使用 Ajax 实现打分评级和添加评论功能
- Ajax 和 XML: 使用 Ajax 实现打分评级和添加评论功能
- Ajax 和 XML: 使用 Ajax 实现 lightbox
- Ajax 和 XML: 使用 Ajax 实现 lightbox
- Ajax 和 XML: 使用 Ajax 实现 lightbox
- Ajax实现评论的顶和踩功能
- 使用xml、php和Ajax实现点赞功能
- jquery实现ajax功能和读取xml
- 使用Ajax评级组件
- 使用Ajax评级组件
- 使用Ajax评级组件
- 使用Ajax评级组件
- 使用Ajax评级组件
- 使用Ajax评级组件
- Ajax 和 XML: 使用 Ajax 实现 lightbox(转载)
- sns 评论ajax分页 和 二级评论ajax 分页 ssh2 实现 源码下载
- AJAX产品评论功能
- 使用mysql、php和Ajax实现点赞功能
- Linux进程编程介绍(一)
- 剖析IT培训市场的五大怪现象
- 常用正则
- PHP对HTML编码字符串的处理
- java反射机制
- Ajax 和 XML: 使用 Ajax 实现打分评级和添加评论功能
- Linux进程编程介绍(二)
- 如何骗女孩子上床。一定要看哦。
- Iframe自适应高度
- Linux进程编程介绍(三)
- JavaScript页面刷新与弹出窗口问题解决方法
- Linux进程编程介绍(四)
- E770装不上RSD的解决方法!
- 想学C语言