问题
My code properly works to insert like or delete like from database. And upon refresh of the page, it will show properly. But, how can I get it to toggle upon clicking? I have searched and tried solutions online, but none worked.
Here's my code:
// PHP CODE TO SEE IF USER ALREADY LIKES VIDEO
<?php
$query272 = "SELECT * FROM video_likes WHERE video_id = :video_id272 AND user_id = :user_id272";
$stmt272 = $pdo->prepare($query272);
$stmt272->bindValue(':video_id272',$id123);
$stmt272->bindValue(':user_id272',$userID);
$stmt272->execute();
$count272 = $stmt272->rowCount();
if($count272 > 0) { $you_like_this = 1; } else { $you_dont_like_this = 1; }
if($you_dont_like_this == 1) {
?>
Ajax Code
<script>
$(function() {
$('#insertLike').click(function () {
var videoID271 = $('#id').val();
var userID271 = $('#userID').val();
console.log('starting ajax');
$.ajax({
url: "./insert-like.php",
type: "post",
data: { id: videoID271, userID: userID271 },
success: function (data) {
var dataParsed = JSON.parse(data);
console.log(dataParsed);
}
});
});
});
</script>
Like Button Form:
<div style="float:left;margin-right:12px" id="like">
<input type="hidden" name="id" id="id" value="<?php echo $id123; ?>" />
<input type="hidden" name="userID" id="userID" value="<?php echo $userID; ?>" />
<input type="hidden" name="you_like_this" id="you_like_this" value="1" />
<button onclick="insertLike(this)" class="insertLike" id="insertLike" style="background:none;border:none;text-decoration:none; color:#DD4400;font-weight:bold">Like</button>
</div>
<?php } else { ?>
Dislike Button Ajax:
<script>
$(function () {
$('#deleteLike').click(function () {
var unlikeVideoID272 = $('#unlikeVideoID').val();
var unlikeUserID272 = $('#unlikeUserID').val();
console.log('starting ajax');
$.ajax({
url: "./delete-like.php",
type: "post",
data: { unlikeVideoID: unlikeVideoID272, unlikeUserID: unlikeUserID272 },
success: function (data) {
var dataParsed = JSON.parse(data);
console.log(dataParsed);
}
});
});
});
</script>
Dislike Form:
<div style="float:left;margin-right:12px" id="unlike">
<input type="hidden" name="unlikeVideoID" id="unlikeVideoID" value="<?php echo $id123; ?>" />
<input type="hidden" name="unlikeUserID" id="unlikeUserID" value="<?php echo $userID; ?>" />
<button onclick="deleteLike(this)" class="deleteLike" id="deleteLike" style="background:none; border:none; text-decoration:none; color:#DD4400; font-weight:bold">Unlike</button>
</div>
PHP Close:
<?php } ?>
EDIT (as requested):
Table users Table likes Table videos
user_id <------- user_id -------> user_id
likes
video_id ------> id
Not using dislikes. Instead, using like, and unlike (when you've already liked it, you can change your mind and unlike it). Unlike will simply remove like from the table.
Once again, the insert into database works fine. I simply need to change the word like to the word unlike after Ajax Success 200. Well, not just the word. The script as well. When like turns into unlike, clicking unlike should like the video again. As if someone is bipolar and keeps changing their mood / opinion. Think of Facebook's like button. You click it. It likes a post. You click it again, it unlikes the post. No page refreshes needed.
回答1:
Step 1: plan database
From your select query, I gather that there are 3 tables involved here:
Video Video_Likes User
video_id --> video_id
user_id <--- user_id
- To find total number of likes for a video, one would
select count(user_id) from video_likes where video_id=?
- To find if a user likes a video, we could simply
select * from video_likes where user_id=? and video_id=?
However, that doesn't work if you actually have a dislike. In that case, we need to add another field to video_likes
:
Video Video_Likes User
video_id --> video_id
user_id <--- user_id
affinity
where affinity= 'Like' | 'Dislike' (I prefer to use human-readable values rather than 'L' | 'D')
Now, the queries would be
select count(user_id) from video_likes where video_id=? and affinity=?
for count of likes or dislikesselect affinity from video_likes where user_id=? and video_id=?
to find out if a user likes or dislikes a video
note: there should be a unique key over video_id and user_id; you can't have more than one status for each video/user combination
Step 2: plan presentation
Adding a couple of basic fields:
Video Video_Likes User
video_id --> video_id
title user_id <--- user_id
affinity name
Simplified script, omitting much of the PHP logic for now
videos.php
<?php
// assuming you already have a PDO object named $pdo...
$sql = "select video.video_id, video.title, likes.total_likes, dislikes.total_dislikes
from Video
left join (
select video_id, count(video_id) total_likes
from Video_Likes
where affinity = :like -- 'Like'
group by video_id
) likes on video.video_id = likes.video_id
left join (
select video_id, count(video_id) total_dislikes
from Video_Likes
where affinity = :dislike -- 'Dislike'
group by video_id
) dislikes on video.video_id = likes.video_id
order by video.title";
$stmt = $pdo->prepare($sql);
$stmt->execute(['like'=>'Like','dislike'=>'Dislike']);
// This is the end of all the PHP logic.
// Now, we will output the view. No more PHP except iteration, variable substitution and minor conditionals
?>
<html>
<head><title>Sample</title></head>
<body>
<h1>Video List</h1>
<table>
<tr>
<th>Video</th>
<th>Likes</th>
<th>Dislikes</th>
</tr>
<?php foreach($stmt as $row): ?>
<tr>
<td><?= htmlentities($row['title']) ?></td>
<td><?= htmlentities($row['likes']) ?? 'No Votes' ?></td>
<td><?= htmlentities($row['dislikes']) ?? 'No Votes' ?></td>
</tr>
<?php endforeach; ?>
</table>
</body>
</html>
Step 3: plan javascript
Assuming JQuery is loaded in the page (not shown above), add ajax transport
As it stands, there are no hooks nor any way to transfer information to ajax. Fix it by adding class and data attribute:
<?php foreach($stmt as $row): ?>
<tr>
<td><?= $row['title'] ?></td>
<td class="video-like" data-video-id="<?= $row['video_id'] ?>">
<?= $row['likes'] ?? 'No Votes' ?>
</td>
<td class="video-dislike" data-video-id="<?= $row['video_id'] ?>">
<?= $row['dislikes'] ?? 'No Votes' ?>
</td>
</tr>
<?php endforeach; ?>
Now, make a couple of listeners and an ajax function just before the </body>
tag:
<script>
// assign this from php
var user_id = "<?= $user_id ?>";
// the document ready section is not strictly needed, but doesn't hurt...
$( document ).ready() {
$('.video-like').on('click', function() {
var video_id = $(this).data('video-id'); // may be data('videoId')
setAffinity(video_id, 'Like');
});
$('.video-dislike').on('click', function() {
var video_id = $(this).data('video-id'); // may be data('videoId')
setAffinity(video_id, 'Dislike');
});
// close document ready
}
function setAffinity(video_id, affinity) {
$.ajax({
url: "./videos.php",
type: "post",
data: { user_id: user_id, video_id: video_id, affinity: affinity },
success: function (data) {
if(data.status == 'success') {
// do something
} else {
// do something else
}
}
});
}
</script>
Step 4: PHP receives data from ajax and responds
Before the logic for getting the page data ($sql = "select video.video_id, video.title, likes.total_likes, dislikes.total_dislikes ..."
), check for a POST submission. This is putting REST transactions into place.
<?php
// assuming you have managed user login and saved user_id in session
session_start();
$user_id = $_SESSION['user_id'] ?? false;
// if there is a POST submission, we know a change to data is being requested.
if($user_id && array_key_exists('video_id',$_POST)) {
// we are returning JSON; there can be no output before this. That's why this is the first order of business.
header("Content-type:application/json");
// early exit on data validation failure
if( !is_numeric($_POST['video_id'] ) {
print json_encode( ['status'=>'failed', 'message'=>'Invalid video selected'] );
die;
}
$video_id = $_POST['video_id'];
// early exit on data validation failure
if( !in_array( ['Like','Dislike'], $_POST['affinity'] ) {
print json_encode( ['status'=>'failed', 'message'=>'You must select Like or Dislike'] );
die;
}
$affinity = $_POST['affinity'];
$sql = "insert into video_likes (video_id, user_id, affinity) values(?,?,?)";
$stmt = $pdo->prepare($sql);
$success = $stmt->execute( [$video_id, $user_id, $affinity] );
// early exit on failure
if(!$success) {
print json_encode( ['status'=>'failed','message'=>'Your selection was not recorded'] );
die;
}
// let's send back the new count of likes and dislikes
$sql = "select count(user_id) total from video_likes where video_id=? and affinity=?";
$stmt= $pdo->prepare($sql);
$stmt->execute([$video_id, 'Likes']);
$likes = $stmt->fetchColumn();
$stmt->execute([$video_id, 'Dislikes']);
$dislikes = $stmt->fetchColumn();
print json_encode( ['status'=>'success', 'likes'=>$likes, 'dislikes'=>$dislikes] );
die;
}
// continue with the page presentation as above...
Step 5: receive PHP response back in browser
Back in javascript function setAffinity()
...
function setAffinity(video_id, affinity) {
$.ajax({
url: "./videos.php",
type: "post",
data: { user_id: user_id, video_id: video_id, affinity: affinity },
success: function (data) {
if(data.status == 'success') {
// you will receive back {data: 'success', likes: $likes, dislikes: $dislikes}
// locate the affected row and update the values
// you may have to create an id for each like and dislike if this doesn't work...
$('.video-like[data-video-id="' +data.likes+ '"]').html(data.likes);
$('.video-dislike[data-video-id="' +data.dislikes+ '"]').html(data.likes);
} else {
alert(data.message);
}
}
});
}
来源:https://stackoverflow.com/questions/59513725/how-to-toggle-between-like-and-unlike-on-ajax-success