I am working on a function that allows a user to up vote a post no more than one time. There are multiple posts on a page so I need to keep track of which posts the user has voted on.
I do that by keeping a total sum of the votes casts. For instance, if a user up votes a post, they should be remove their vote by down voting once, or change their original up vote to a down vote by down voting twice.
The first time a vote is cast, I initialize the $_SESSION variable to 0. A down vote takes it to -1 and an up vote takes it to 1.
Here is the PHP function for up vote (the down vote function is similar):
function upVote($post_id) {
global $databaseController;
if(!isset($_SESSION[$post_id])) {
$_SESSION[$post_id] = 0;
}
if($_SESSION[$post_id] <= 0) {
$sql = "SELECT likes FROM posts WHERE id='" . $post_id . "'";
$results = $databaseController->select($sql);
if($results && $results->num_rows == 1) {
$results = $results->fetch_assoc();
$new_likes = ++$results['likes'];
try {
$databaseController->startTransaction();
$sql = "UPDATE posts SET likes=" . $new_likes . " WHERE id=" . $post_id;
$databaseController->update($sql);
if($databaseController->commit()) {
$_SESSION[$post_id] = ++$_SESSION[$post_id];
return true;
}
} catch (Exception $e) {
$databaseController->rollback();
return false;
}
}
}
return false;
}
The $_SESSION[$post_id] is always being reset to 0 each time the function is called allowing the user to vote as many times as they want.
Why is this happening? It seems to me that the variable should only be set to 0 if the user has never voted on the post, else it just pulls up the variable, sees that it exists, and modifies it.
Is there anything wrong with my logic? Or am I not using $_SESSION variables in the correct way?
Related
I want to use sessions to track unique page views. Not a very robust method, I know, but sufficient for what I want to do.
On the first page load the session variable is set and a field in the database increments. On subsequent page views it does not increment, because the increment is conditional on the session variable not being set.
This is my code:
$pagenumber = 1;
//other stuff here...
session_start();
if (!isset($_SESSION[$pagenumber])) {
$storeview = mysqli_query($dbconnect, "UPDATE tblcount SET views=views+1 WHERE id='$pagenumber'");
$_SESSION[$pagenumber] = $pagenumber;
}
echo $_SESSION[$pagenumber];
$Recordset1 = mysqli_query($dbconnect, "SELECT views FROM tblcount WHERE id = '$pagenumber'");
$row_Recordset1 = mysqli_fetch_assoc($Recordset1);
echo "Viewed ".$row_Recordset1['views']." times";
The first echo is only there for testing. It echoes the value just fine on page refresh and the increment works the first time, but the view count continues to increment on every page refresh, which it shouldn't. I can't see why.
I found a similar question:
PHP: Unique visits/hits to specific items using cookies/ip but I ran into a similar issue with the solution offered there.
Help appreciated!
Problems:
You are updating in tblCount EACH time, because your session is closed each time your script finishes.
SO: Put the session_start()call as the FIRST LINE in code.
It's not permitted to set an integer as $_SESSION variable. So if you set $_SESSION[$pagenumber] = 'something', then you gain the following notice:
( ! ) Notice: Unknown: Skipping numeric key 1 in Unknown on line 0
Quite... not understandable. For details see this answer.
Solution:
Add your $pagenumber as index in an array (here pagenumbers) and that array inside the $_SESSION variable. No notice anymore.
session_start();
$pagenumber = 1;
if (!isset($_SESSION['pagenumbers'])) {
$_SESSION['pagenumbers'] = array();
}
if (!isset($_SESSION['pagenumbers'][$pagenumber])) {
updateViews($pagenumber);
$_SESSION['pagenumbers'][$pagenumber] = $pagenumber;
}
echo 'Page number: ' . $_SESSION['pagenumbers'][$pagenumber] . '<br/>';
$views = getViews($pagenumber);
echo '<pre>Viewed ' . print_r($views, true) . ' times</pre>';
Note: I used my functions to test. They just replace your db-processing code.
Just tested. This also works.
session_start();
// Get page name
$page_url = $_SERVER['REQUEST_URI'];
// Create the session ID. Will act as visitor username
if(!isset($_SESSION['id'])){
$_SESSION['id'] = session_id();
// For the visit to the first page
$visit_id = $_SESSION['id'];
}else{
// For subsequent visits to any page
$visit_id = $_SESSION['id'];
}
/******************
Query DB. Insert only one visit per page per session.
It means we need a count for each page to get its total visits.
Or a count for all records to get site total visits.
************************************/
$query_visits_table = mysqli_query($db_connect, "SELECT * FROM tblcount WHERE (visit_id='$visit_id') AND (page_name='$page_url')");
if(mysqli_num_rows($query_visits_table) > 0){
// Do nothing if this page has been visited during this session
}else{
mysqli_query($db_connect, "INSERT INTO tblcount (visit_id, page_name, visit) VALUES('$visit_id', '$page_url', '1')");
}
// Get site total visits
$query_site_visits = mysqli_query($db_connect, "SELECT * FROM tblcount");
// For a specific page
$query_specific_page_visit = mysqli_query($db_connect, "SELECT * FROM tblcount WHERE page_name='$page_url'");
if(isset($query_site_visits) && isset($query_specific_page_visit)){
$site_total_visits = mysqli_num_rows($query_site_visits);
$specific_page_visit = mysqli_num_rows($query_specific_page_visit);
echo 'Site total visits is '. $site_total_visits . '<br />';
echo 'Total visits for ' . $page_url . ' is ' . $specific_page_visit;
exit();
}
Good day # all.
I've this code snippet which's aim is to display the Exam this user is qualified to take based on the courses registered for. It would display the Exam Name, Date Available, Passing Grade and either Take Exam link if he/she hasn't written or View Result if he/she has written previously.
/*Connection String */
global $con;
$user_id = $_SESSION['user_id']; //user id
$courses = parse_course($user_id); //parse course gets the list of registered courses (Course Codes) in an array
foreach ($courses as $list)
{
$written = false;
$list = parse_course_id($list); //parse_course_id gets the id for each course
$ers = mysqli_query($con, "Select * from exams where course_id = '$list'");
while ($erows = mysqli_fetch_assoc($ers)) {
$trs = mysqli_query($con, "Select * from result_data where user_id = '$user_id'");
while ($trows = mysqli_fetch_assoc($trs)) {
if ($trows['user_id'] == $user_id && $trows['exam_id'] == $erows['exam_id'])
$written = true;
else
$written = false;
}
if($written)
{
echo "<tr><td>".$erows['exam_name']."</td><td>".$erows['exam_from']." To ".$erows['exam_to']."</td><td>".$erows['passing_grade']."%</td><td>".'View Result '."</td></tr>";
$written = false;
}
else
{
echo "<tr><td>".$erows['exam_name']."</td><td>".$erows['exam_from']." To ".$erows['exam_to']."</td><td>".$erows['passing_grade']."%</td><td>".'Take Exam '."</td></tr>";
$written = false;
}
}
}
But It only displays one View Result entry even if I've taken more than one exam. It shows the recent entry. Please what am I missing?
Untested, but here's how I would do it.
I've assumed $user_id is an integer. I'm a bit worried about it being used in SQL without any sanitization. I can't guarantee anything else you're doing is secure either because I can't see your other code. Please read: http://php.net/manual/en/security.database.sql-injection.php
(Oh I see someone already commented on that - don't take it lightly!)
Anyway, my approach would be to collect the user's written exam IDs into an array first. Then loop through the available exams and check each exam id to see if it's in the array we made earlier.
I wouldn't bother looking into the join advice unless you find this is performing poorly. In many systems it would be common to have 3 functions in this situation, one that generates $users_written_exam_ids ones that pulls up something like $all_available_exams and then this code which compares the two. But because people are seeing both queries here together there is a strong temptation to optimize it, which is cool but you probably just want it to work :)
<?php
global $con;
// Get the user id. Pass through intval() so no SQL injection is possible.
$user_id = intval($_SESSION['user_id']);
// Parse course gets the list of registered courses (Course Codes) in an array
$courses = parse_course($user_id);
foreach ($courses as $list)
{
// Gets the id for each course
$list = parse_course_id($list);
$users_written_exam_ids = array();
$trs = mysqli_query($con, "SELECT exam_id FROM result_data WHERE user_id = '$user_id'");
while ($trows = mysqli_fetch_assoc($trs))
{
$users_written_exam_ids[] = $trows['exam_id'];
}
$ers = mysqli_query($con, "SELECT * FROM exams WHERE course_id = '$list'");
while ($erows = mysqli_fetch_assoc($ers)) {
echo '<tr><td>' . $erows['exam_name'] . '</td><td>' . $erows['exam_from']
. ' To ' . $erows['exam_to'] . '</td><td>' . $erows['passing_grade']
. '%</td><td>';
if (in_array($erows['exam_id'], $users_written_exam_ids))
{
echo 'View Result';
}
else
{
echo 'Take Exam';
}
echo '</td></tr>';
}
}
I have a very simple PHP function which checks the DB if the post is saved in the user's bookmarks or not. If it is saved as a bookmark in the table 'bookmarks', it should return a link to the bookmarks, if not, it should return a simple button.
This is the code that calls the function:
echo bookmark($id,'stories');
This is the PHP function:
function bookmark($id,$column) {
global $db_conx;
if($column = 'stories') { $col = 'storid'; }
elseif($column = 'discussions') { $col = 'discid'; }
elseif($column = 'articles') { $col = 'articleid'; }
elseif($column = 'videos') { $col = 'videoid'; }
else $col = 'resid';
$result = mysqli_query($db_conx, "SELECT * FROM bookmarks WHERE '$col'='$id' AND username='$log_username' LIMIT 1");
$num_rows = mysqli_num_rows($result);
if ($num_rows > 0) {
return "<a class='rllink' title='Saved in your bookmarks' href='https://hangar.flights/bookmarks'><i class='fa fa-bookmark'></i></a>";
}
else return "<a class='rllink' href="xxxx" title='Save this in your bookmarks'><i class='fa fa-bookmark-o'></i></a>";
};
For some weird reason, this doesn't seem to be working, although my other similar functions do work. Everywhere I call this function (with the correct parameters) it returns the else statement, even if the specific id is saved in the bookmarks and should return the first statement with a link to the bookmarks.
Anyone who sees what's wrong with it? I have tried adapting and changing it but nothing works.
You are using assignment-in-if:
if($column = 'stories')
When executed, this is what happens:
the value of $column becomes the string 'stories'
the if statement checks whether the new value of $column is truthy
This is almost certainly not what you want, and you'll probably want to do comparing-if statements that don't change the value(s) of the things you check:
if($column == 'stories')
This will check whether $column is currently equal to the string 'stories' without changing the value.
I have a webpage with a button on it. When the button it clicked it sends a request to a page with this code on it
$userName = "tdscott";
$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$divID = explode('?', $url);
$id = 0;
$id = explode('#',$divID[1])[1];
$func = $divID[2];
$find = mysqli_fetch_array(mysqli_query($con,"SELECT likes FROM status WHERE id='$id'"))['likes'];
if ($func == "addLike")
{
$promoted = $userName . "-";
mysqli_query($con, "UPDATE status SET promotedBy = CONCAT(promotedBy,'$promoted') WHERE id='$id'");
$find++;
mysqli_query($con,"UPDATE status SET likes = '$find' WHERE id='$id'");
echo $find;
}//end if addLike
elseif($func === "removeLike")
{
echo "ERROR";
}//end if removeLike
elseif ($func === "getLikes")
{
echo $find;
}//end if getLikes
mysqli_close($con);
I left of the database connection information. But for some reason when this is called it produces inaccurate results. For example... Sometimes it will put multiple instances of $promoted in the promotedBy field in my table and sometimes it will update other rows in the table that the id does not equal the current $id. I am wondering if somehow it is getting the $id variable mixed up from when I submitted it with a different value before. Is there a way to reset the variables before I call it each time?
Please note: In the if statement, we are only looking at the addLike portion. I included the other just in case it was causing the problem.
unset($id);
Sorry should have done more research.
Below shows my coding to increment the number of publication view for my website. Right now it increments whenever I click refresh. I have used session command on some part of the code however it doesn't work, it increments whenever I click refresh. I want to understand how can I not make user to increment the session if they are in same session.
It will be very grateful if you can help me.
<?php
session_start();
$_SESSION['counted'] = true;
if (isset($_GET['id'])) {
$file_id = ($_GET['id']); //$id is a new vairable given value to the id selected in publication.php
if ($file_id <= 0) { //check if id is less than or equal to 0
die('The ID is invalid, please check the technical process!');
} else {
mysql_query("SELECT * FROM files WHERE id='$file_id'");
if (!isset($_SESSION['id'])) {
$_SESSION['id'] = 0;
$query = "UPDATE files SET visitors=visitors+1 WHERE id='$file_id'";
mysql_query($query);
mysql_close();
session_destroy();
}
}
}
?>
The reason it is incrementing each time you refresh is because of the following line of code:
session_destroy();
What it's doing is (as the name depicts) destroying your session after each increment, so next time the page loads, $_SESSION['id'] is no longer instantiated, so your if(!isset($_SESSION['id'])) always returns true.
You can try the following:
<?php
session_start();
$_SESSION['counted'] = true;
if (isset($_GET['id'])) {
$file_id = ($_GET['id']); //$id is a new variable given value to the id selected in publication.php
if ($file_id <= 0) { //check if id is less than or equal to 0
die('The ID is invalid, please check the technical process!');
} else {
mysql_query("SELECT * FROM files WHERE id='$file_id'");
if (!isset($_SESSION['id'][strval($_GET['id'])])) {
$_SESSION['id'][strval($_GET['id'])] = true;
$query = "UPDATE files SET visitors=visitors+1 WHERE id='$file_id'";
mysql_query($query);
mysql_close();
}
}
}
?>
I've used an array $_SESSION['id'] to store a key for each different page ID, then each time we test if we need to increment your counter, we check if an array key exists for that page, if it does, we don't increment.
Hope this helps! :)