【发布时间】:2012-10-05 17:55:43
【问题描述】:
所以我正在建立一个像 Flickr 这样的 PHP 网站,除了这些照片可以评级。所以我在 AJAX 中设置了评分系统,这样当用户单击星号对照片进行评分时,照片上的星号会反映计算出的新评分。 (照片的等级由黄色或空白的 10 颗星表示)。
当您将鼠标悬停在星星上时,星星会做出反应,它们会在您的光标指向的地方亮起。当您单击一个星时,相应的值会记录在 photo_rating 表中并在 photo 表中更新。然后新计算的评分会通过星星反映出来。
更新这几乎都归结为这个调用没有返回正确的评级,它仍然在页面加载时返回照片的原始评级。而不是通过 AJAX 保存在数据库中的新评级(即使数据库中的值已更改)
onmouseout="stars_current_rating(<?php echo Photograph::find_by_id($_GET['id'])->rating;?>);"
问题出在这里:点击后,星星会更新为正确的新计算评级。但是当我将鼠标移回星星上时,鼠标移开。星级评分会回到用户首次加载页面时的原始评分。因此,正在反映的评级是页面加载时从数据库中提取的评级。不是现在位于照片表评级列中的值。
最初我使用的是 $photo->rating,但我认为自从我使用 AJAX 后,该值就不再被计算了。于是我将 onmouseout 切换为调用 Photo::find_by_id($_GET['id'])->rating;它应该通过从其 id 检查数据库并获取当前评级来实例化一个新对象。但即使这样似乎也没有给我更新的价值。
我使用了 firebug、firePHP,并且正在进行分析,以查看当我单击并将鼠标悬停在这些方法上时传递给这些方法的确切值。出于某种原因,新评级只是从数据库中提取,在用户投票后立即显示新值。但是,当您将鼠标悬停在星星上时,它们会回到您加载页面时的状态。无论如何,我可以在不刷新整个页面的情况下将更新后的值反映在下面的代码中吗?如果我刷新页面,那么它可以工作,但重点是通过 AJAX 完成所有操作,因此不必重新加载整个页面......
这是在页面上设置调用的方式。
<div id="rating" class="rating">
<?php
for($i=1; $i<11; $i++){
?>
<a id="rating_star<?php echo $i ?>" href="#" onmouseover="decide_rating(<?php echo $i ?>);"
onmouseout="stars_current_rating(<?php echo Photograph::find_by_id($_GET['id'])->rating;?>);"
onmousedown="set_rating(<?php echo $photo->id.", ".$i ?>);">
<img id="star<?php echo $i ?>" class="rating_star" src=
<?php
// keeps stars always set at rating for photo when not being rated
if($photo->rating >= $i){
echo "images/assets/rating_star.png";
} else {
echo "images/assets/rating_star_off.png";
}
?>
/>
</a>
<?php } ?>
</div>
这是我的 ratings.js 文件,其中包含上面用于 onmouseactions 的 3 个(我知道 decision_rating 和 stars_current_rating 是相同的代码,当我将它们设置为不同的页面时它们是不同的,其中逻辑不同,但更新不起作用,所以我回到这个更简单的例子)
// Makes stars light up, up to where you have your cursor pointing
// pass in current rating of star hovered over
function decide_rating( r ){
for(var i=1; i<=10; i++){
var star = document.getElementById("star"+i);
if(i<=r){
star.src = "images/assets/rating_star.png";
} else {
star.src = "images/assets/rating_star_off.png";
}
}
return false;
}
// defaults the stars to light up with the current rating
function stars_current_rating(r){
for(var i=1; i<=10; i++){
var star = document.getElementById("star"+i);
if(i<=r){
star.src = "images/assets/rating_star.png";
} else {
star.src = "images/assets/rating_star_off.png";
}
}
return false;
}
function set_rating(pid, rating){
if (window.XMLHttpRequest){// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4 && xmlhttp.status==200){
// no message to be displayed
//document.getElementById("message").innerHTML=xmlhttp.responseText;
// for this to work ratings.js must be before this file when linked to
// set_ratings is echoing the $photo->rating for the calling pid
// as the xmlhttp.responseText
stars_current_rating(xmlhttp.responseText);
}
}
xmlhttp.open("GET","../includes/set_rating.php?pid="+pid+"&rating="+rating,true);
xmlhttp.send();
}
我在我的数据库中设置了 2 个表。一种是具有 user_id、photo_id 和 rating 的 photo_rating。 photo 表还有一列表示其当前评级(计算为 photo_rating 中相应行的平均值)。
下面是AJAX调用的set_rating.php文件
<?php
// This file is called by the ratings.js function set_rating
// echo output is used by to update the current rating of the
// photo after it has been saved in the database
require_once('initialize.php');
// create new photo rating and set up attributes
if(isset($session->user_id)){
$pr = new PhotoRating( $_GET['pid'], $session->user_id, $_GET['rating']);
} else {
$pr = new PhotoRating( $_GET['pid'], NULL, $_GET['rating']);
}
// save the rating in photo_ratings table
// and the rating in the photograph table
$pr->save_rating_update_photo();
echo Photograph::find_by_id($_GET['pid'])->rating;
?>
这些是在 PhotoRating 中被调用的函数
// saves the current photo_rating into the database
// Then calls update photo rating up update the
// rating in the photo database table
function save_rating_update_photo(){
if($this->save()){
// Success
$message = "entry saved in photo_rating";
//$session->message("{$photo->filename} was uploaded");
} else {
// Failure
$message = join("<br />", $this->errors);
}
$this->update_photo_rating();
}
function update_photo_rating(){
$photo = Photograph::find_by_id($this->p_id);
$newRating = ($this->rating + self::sum_all_ratings($this->p_id))/($this->count_all()+1);
$photo->rating = $newRating%10;
if($photo->save()){
// Success
} else {
// Failure
$message = join("<br />", $photo->errors);
}
}
任何见解都将不胜感激,自从我昨天晚些时候开始测试以来,我一直在敲桌子。我知道我可以重新加载页面,但我觉得这否定了通过 AJAX 实现这一切的效率。
【问题讨论】:
-
对于这里的大多数人来说,这肯定属于“太长,没读过”的类别。你能把问题隔离一下吗?
-
你能链接到这个代码的例子吗?可能会更容易调试
-
是的,我明白这一点,这就是为什么我把我的问题放在首位。我试图尽可能具体。然后我展示了所有与之相关的代码。最好有太多的信息而不是足够的信息,特别是当不是你编写代码时......对吗? frompointatobeyond.com/photo_social/public/photo.php?id=48
-
"但是,当您将鼠标悬停在星星上时,它们会返回到您加载页面时的状态。无论如何,我可以在不刷新的情况下将更新后的值反映在下面的代码中整个页面?”。所以在页面加载 PHP(服务器端)负责显示当前的星级。什么是等效的 JS 代码在 XHR 发布后立即执行完全相同的操作以设置点击评分?它不存在还是不能正常工作?
-
@ficuscr 在 AJAX 调用的最后一行我调用 stars_current_rating(xmlhttp.responseText);这是我唯一一次在用户选择他们的评级后点亮正确的星星。在此之后,使用带有 stars_current_rating(rating;?>);" 的 onmouseout 函数的后续调用没有给我已存储的更新值照片表中的评分
标签: php ajax database onmouseout