-1

所以我正在建立一个像 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>

这是我的 rating.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 实现这一切的效率。

4

1 回答 1

1

在简要查看您的问题/问题并检查您的实时网站的来源之后,我会这样做:

在 ratings.js 的顶部,添加:

// Global variable to hold the current rating
var star_rating = 0;

改为stars_current_rating(r)

// defaults the stars to light up with the current rating
function stars_current_rating(){ // no "r"
    for(var i=1; i<=10; i++){
        var star = document.getElementById("star"+i);
        if(i<=star_rating){ // !!!
            star.src = "images/assets/rating_star.png";
        } else {
            star.src = "images/assets/rating_star_off.png";
        }
    }
    return false;
}

set_rating(pid, rating)中,将当前第 48 行更改为:

star_rating = xmlhttp.responseText;
stars_current_rating();

photo.php,在每个 中a,将 更改onmouseout为:

onmouseout="stars_current_rating();"

您没有得到您期望的结果的原因是评级的值被硬编码到onmouseout函数调用中。在 javascript 中拥有一个随 xmlhttp 响应而变化的变量是至关重要的。

为了在页面加载时也能正常工作,请在 photo.php 中创建一个脚本部分,以star_rating正确设置(通过<?php echo Photograph::find_by_id($_GET['id'])->rating;?>

希望这可以帮助!

于 2012-10-05T20:06:27.883 回答