Reputation:
I'm trying to implement upvote/downvote system.The user clicks on the upvote or downvote button its triggers the AJAX code the votes is inserted or updated in the database.
This triggers AJAX request on click.
echo '<i id="'.$row['postID'].'" class="fa fa-chevron-up vote_up" aria-hidden="true"></i>';
echo '<i id="'.$row['postID'].'" class="fa fa-chevron-down vote_down" aria-hidden="true"></i>';
This is the ajax code -
$(document).ready(function () {
$("i.vote_up").click(function () {
the_id = $(this).attr('id');
$.ajax({
type: "POST",
data: "action=upvote&id=" + $(this).attr("id"),
url: "vote.php",
success: function (msg) {
alert("Success");
},
error: function () {
alert("Error");
}
});
});
});
$(document).ready(function () {
$("i.vote_down").click(function () {
the_id = $(this).attr('id');
$.ajax({
type: "POST",
data: "action=downvote&id=" + $(this).attr("id"),
url: "vote.php",
success: function (msg) {
alert("Success");
},
error: function () {
alert("Error");
}
});
});
});
This is the code that handles votes.
<?php
require('includes/config.php');
$action = $_POST['action'];
$postID = $_POST['id'];
$memberID = $_SESSION['memberID'];
switch ($action) {
case "upvote":
try {
$stmt = $db->prepare('SELECT memberID,postID,voteType FROM votes WHERE postID = :postID AND memberID =:memberID');
$stmt->execute(array(
':postID' => $postID,
':memberID' => $memberID
));
$row = $stmt->fetch();
if ($row['voteType'] == "up") {
$stmt = $db->prepare('DELETE FROM votes WHERE postID = :postID AND memberID =:memberID');
$stmt->execute(array(
':postID' => $postID,
':memberID' => $memberID
));
$stmt = $db->prepare('UPDATE posts SET upVote = upVote -1 WHERE postID = :postID');
$stmt->execute(array(
':postID' => $postID
));
}
else if ($row['voteType'] == "down") {
$voteType = "up";
$stmt = $db->prepare('UPDATE votes SET voteType = :voteType WHERE postID = :postID AND memberID =:memberID');
$stmt->execute(array(
':voteType' => $voteType,
':postID' => $postID,
':memberID' => $memberID
));
$stmt = $db->prepare('UPDATE posts SET upVote = upVote +1, downVote = downVote -1 WHERE postID = :postID');
$stmt->execute(array(
':postID' => $postID
));
} else if ($row['memberID'] == null) {
$voteType = "up";
$stmt = $db->prepare('INSERT INTO votes (postID,memberID,voteType) VALUES (:postID, :memberID, :voteType)');
$stmt->execute(array(
':postID' => $postID,
':memberID' => $memberID,
':voteType' => $voteType
));
$stmt = $db->prepare('UPDATE posts SET upVote = upVote +1 WHERE postID = :postID');
$stmt->execute(array(
':postID' => $postID
));
}
}
catch (PDOException $e) {
echo $e->getMessage();
}
break;
case "downvote":
try {
$stmt = $db->prepare('SELECT memberID,postID,voteType FROM votes WHERE postID = :postID AND memberID =:memberID');
$stmt->execute(array(
':postID' => $postID,
':memberID' => $memberID
));
$row = $stmt->fetch();
if ($row['voteType'] == "down") {
$stmt = $db->prepare('DELETE FROM votes WHERE postID = :postID AND memberID =:memberID');
$stmt->execute(array(
':postID' => $postID,
':memberID' => $memberID
));
$stmt = $db->prepare('UPDATE posts SET downVote = downVote -1 WHERE postID = :postID');
$stmt->execute(array(
':postID' => $postID
));
} else if ($row['voteType'] == "up") {
$voteType = "down";
$stmt = $db->prepare('UPDATE votes SET voteType = :voteType WHERE postID = :postID AND memberID =:memberID');
$stmt->execute(array(
':voteType' => $voteType,
':postID' => $postID,
':memberID' => $memberID
));
$stmt = $db->prepare('UPDATE posts SET downVote = downVote +1, upVote = upVote -1 WHERE postID = :postID');
$stmt->execute(array(
':postID' => $postID
));
} else if ($row['memberID'] == null) {
$voteType = "down";
$stmt = $db->prepare('INSERT INTO votes (postID,memberID,voteType) VALUES (:postID, :memberID, :voteType)');
$stmt->execute(array(
':postID' => $postID,
':memberID' => $memberID,
':voteType' => $voteType
));
$stmt = $db->prepare('UPDATE posts SET downVote = downVote +1 WHERE postID = :postID');
$stmt->execute(array(
':postID' => $postID
));
}
}
catch (PDOException $e) {
echo $e->getMessage();
}
break;
}
?>
This is all working fine, but I want to know if there is any other way to do this? And also how can I make this code safe to use on a website ?
Upvotes: 0
Views: 1813
Reputation: 675
If you want it more secure, you should bind your parameter before adding them to the database
$stmt = $db->prepare('UPDATE posts SET downVote = downVote -1 WHERE postID = :postID');
$stmt->execute(array(':postID' => $postID));
will become:
$stmt = $db->prepare('UPDATE posts SET downVote = downVote -1 WHERE postID = :postID');
$stmt->bindParam(":postID", $postID, 1); //1 is the datatype for Int; 2: for String; 0 for Bool
$stmt->execute();
http://php.net/manual/en/pdostatement.bindparam.php
Also it will be good to check if the value exist when you get it from "POST"
$postID = $_POST['id'];
could become
(isset($_POST['id'])) ? $postID = $_POST['id'] : $postID = 0
And an other thing I could recommend you would be to hide your page name in your ajax request.
url: "vote.php",
Use RewriteRule in your .htaccess to hide the name of the url then in your ajax request it will become something like
url: "request-vote"
https://mediatemple.net/community/products/dv/204643270/using-htaccess-rewrite-rules
+++ UPDATE - ANSWER FOLLOWING REPLY FROM @Mahim Parsai +++
First to update your ajax request, you need to return some value. In your code your are updating the database, but not returning anything.
First I will create some variable to hold your downVote and upVote, I will also create a variable to hold the result for your ajax request.
$downVote = 0; //will hold the result from the database
$upVote = 0; //will hold the result from the database
$ajax_response=[]; //set an empty array where we will store our result for the ajax request
I give you an example on how to get the value of downVote from your database and send it to your ajax request
//get the value from the database
$stmt = $db->prepare('SELECT downVote FROM posts WHERE postID=:postID');
$stmt->bindParam(':postId', $postID, 1);
$stmt->execute();
$row = $stmt->fetch(5); //fetch the result from your request, (5) means I want to get an object as return
$downVote = $row->downVote; // store the value to the variable set at the beginning, downVote is the name of the column in your table, here we accessing the object
Just before the "}" of your "catch" add the value to the array for the ajax response
$ajax_response['downVote'] = $downVote;
//also let your script know that we succeed this downVote, so let's add it to the array
$ajax_response['status'] = "success";
So in your catch method add this
$ajax_response['status'] = "error";
If your also want to track the error from your ajax request, add this in your catch method
$ajax_response['error'] = $e->getMessage();
At the end of your script send the array to your ajax request. You need to encode the result to json to be read by ajax
echo json_encode($ajax_response);
And don't forget to close your mysql connection
$db=null;
From your ajax request now you can just do
success: function (msg) {
if(msg.status=="success"){
//we succeed
var downVote = msg.downVote //the result from the database
}
else{
//we return error
alert(msg.error);
}
},
error: function () {
alert(msg.error);
}
Upvotes: 1