How to toggle between like and unlike on Ajax success?

你说的曾经没有我的故事 提交于 2020-01-20 09:09:25

问题


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 dislikes
  • select 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!