Итак, я создаю PHP-сайт, такой как Flickr, за исключением того, что эти фотографии можно оценивать. Поэтому я настраиваю систему оценок в AJAX, чтобы, когда пользователь нажимал на звезду, чтобы оценить фотографию, звезды на фотографии отражали новый вычисленный рейтинг. (рейтинг фотографии обозначен 10 желтыми или пустыми звездами).
Звезды реагируют так, как должны, когда вы наводите на них курсор, они загораются там, где указывает ваш курсор. Когда вы нажимаете звездочку, соответствующее значение регистрируется в таблице photo_rating и обновляется в таблице фотографий. Затем вновь вычисленный рейтинг отражается через звезды.
ОБНОВЛЕНИЕ Практически все сводится к тому, что этот вызов не возвращает правильную оценку, он по-прежнему возвращает исходную оценку фотографии при загрузке страницы. А не тот новый рейтинг, который сохранился в БД через AJAX (хотя значение в БД изменено)
onmouseout="stars_current_rating(<?php echo Photograph::find_by_id($_GET['id'])->rating;?>);"
ЗДЕСЬ проблема: после нажатия звезды обновляются с правильным недавно рассчитанным рейтингом. Но когда я снова наведу курсор мыши на звезды, тогда мышка исчезнет. Звездный рейтинг возвращается к исходному рейтингу, который был у него, когда пользователь впервые загрузил страницу. Таким образом, отображаемый рейтинг — это то, что было извлечено из базы данных при загрузке страницы. Не то значение, которое сейчас находится в столбце рейтингов таблицы фотографий.
Первоначально я использовал $photo->rating, но я понял, что, поскольку я использовал AJAX, это значение больше не вычислялось. Затем я переключил onmouseout на вызов Photograph::find_by_id($_GET['id'])->rating; который должен создавать экземпляр нового объекта, проверяя базу данных по его идентификатору и получая текущий рейтинг. Но даже это, похоже, не дает мне обновленного значения.
Я использовал 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, который содержит 3, использованные выше для onmouseactions (я понимаю, чтоsolve_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 таблицами в моей базе данных. Одним из них является photo_rating, который имеет user_id, photo_id и рейтинг. В таблице фотографий также есть столбец с текущим рейтингом (который рассчитывается как среднее значение соответствующих строк в photo_rating).
Ниже приведен файл set_rating.php, который вызывает AJAX.
<?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.