How to make a manual 'like' function (like facebook) using MySQL - php

I am using MySQL and cPANEL for making my website. I'm having a problem in figuring out how to make manual likes function (Facebook like button, or YouTube thumbs up button).
Am I going in the right way to make a "like" button in my website?
VIDEOTABLE:
+----+----------+-----------+
| ID | VIDEO URL| LIKES |
+----+----------+-----------+
| 1 | example 1| 5774 |
| 2 | example 2| 9654 |
| 3 | example 3| 1254 |
| 4 | example 4| 7656 |
| 5 | example 5| 6757 |
| 6 | example 6| 5675 |
| 7 | example 7| 4565 |
+----+----------+-----------+
ID is my serial
VIDEO_URL is my page link or the video link
likes is the users liking this
So, to like the video when USER will clicks the like button without login it will redirect and show the login panel. Then, user will login into it via FACEBOOK or TWITTER so the site can get the USER_ID
Ones the user logins there likes option their will be this code (NOT SURE)
SQL> UPDATE VIDEOTABLE
SET ID = '3', LIKES = ????;
How can i increase +1 value in the table? And then when the USER likes it, the site refreshes and shows the latest value (by increasing by +1).
My Second Problem = How can i restrict the user by giving only one chance to increase the like) and to undo Rollback Query.

You should be able to use the following:
UPDATE VIDEOTABLE SET LIKES=LIKES+1 WHERE ID=3;
However, it may be wise to set a separate lookup table that indicates whether a particular user has already 'liked' something, so that they may not 'like' it more than once.
That table would look like this:
tblLikesLookup
+----+--------+--------+
| ID | videoID| userID |
+----+--------+--------+
| 1 | 1 | 10 |
| 2 | 3 | 7 |
| 3 | 2 | 10 |
| 4 | 8 | 8 |
| 5 | 6 | 8 |
+----+--------+--------+
You could even use this table in place of your VIDEOTABLE to store your likes. To get the number of likes for any given video,
SELECT COUNT(*) FROM tblLikesLookup WHERE videoID=[videoID];
or for all videos,
SELECT COUNT(*) FROM tblLikesLookup GROUP BY videoID;
This may eventually become slow as the volume to your site increases, in which case using a separate counter like the one you have above will come in handy.

if i understand you right,
you can simple increase any number like that:
update VIDEOTABLE set LIKES = LIKES + 1 where ID = ...
so as the same to reduce likes
update VIDEOTABLE set LIKES = LIKES - 1 where ID = ...
it is not important what the user id is. You need video ID
EDIT:
if you want to prevent multiple likes, you need a new table too.
TABLE: USER_TO_LIKES
id | user_id | video_id
so you must firstly check if user liked it before:
$c = mysql_num_rows(mysql_query("select id from USER_TO_LIKES where video_id = 11 and user_id = XX"));
if($c == 0){
mysql_query("update VIDEOTABLE set LIKES = LIKES + 1 where ID = 11 ");
mysql_query("insert into USER_TO_LIKES set video_id = 11, user_id = XX");
}
If unlike:
$c = mysql_num_rows(mysql_query("select id from USER_TO_LIKES where video_id = 11 and user_id = xx"));
if($c > 0)
{
mysql_query("update VIDEOTABLE set LIKES = LIKES - 1 where ID = 11");
mysql_query("delete from USER_TO_LIKES where video_id = 11 and user_id = XX");
}
thats it.
EDIT2: see above

You Will Need the video id And The User That has clicked And Another Table(Called Liked_People) For People Who Has Already Liked Something like that:
+-------+---------+
|UserId |VideoId |
+-------+---------+
|1 |5739 |
+-------+---------+
Now Wen The User Click On Like Send An XMLHTTP request to that PHP function:
function Like($usrid , $vidid){
//usrid = userid And vidid = video id
$Comm1 = $Con->prepare("SELECT * FROM Liked_People WHERE UserId = ? And VideoId = ?");
$Comm1->execute(Array($usrid , $vidid);
if($Comm1->rowCount() == 0){
$Comm2 = $Con->prepare("INSERT INTO Liked_People (UserId , VideoId) VALUES (?,?)");
$Comm2->execute(Array($usrid , $vidid));
$Comm3 = $Con->prepare("SELECT Likes FROM VideoTable WHERE Id = ?");
$result = $Comm3->Execute(Array($vidid));
$final = $result + 1;
$Comm4 = $Con->prepare("UPDATE VideoTable SET Likes=? WHERE ID = ?");
$Comm4->Execute(Array($final , $vidid));
}else { return false;}
}
And That is but if you want to get A list of the usernames that has liked lets say that you have the People Table Like That:
+-------+--------------+
|Id |Username |
+-------+--------------+
|1 |Ahmad Mehmet |
+-------+--------------+
And This is the Code:
function get_likers($vidid){
if($vidid == null or $vidid == "" or $vidid == 0){
return false;
}
$Comm1 = $Con->prepare(SELECT UserId FROM Liked_People WHERE VideoId = ?);
$Comm1->Execute(Array($vidid));
$arr = $Comm1->fetchAll();
$finale = Array();
$i = 0;
foreach($arr as $row){
$Comm = $Con->Prepare("SElECT Username WHERE Id = ?");
$finale[$i] = $Conm->Execute(Array($row[0]));
$i++;
}
return $finale
}
This function is just for backups and Not essential.
function Work_Array($Arr){
echo '<table border="2">';
echo '<tr><th>Users That Has Liked</th></tr>';
foreach($Arr as $el){
echo"<tr><td>";
echo $el;
echo "</td></tr>";
}
echo "</table>";
}
Called Like That:
work_array(get_likers($vidid));
Questions?:D

Related

How to update data as null in mysql using php loop?

I have a table named users with a column called user_subs. It looks like this.
In user_subs I have stored the specific users session username. Lets say this specific users name is James.
Now how would I loop through a specific user_subs looking for "James" and remove him from that specific user_subs without removing all the other names.
This is what I have so far and the only problem is, its deleting all the usernames in user_subs instead of just "James".
if(isset($_GET['p_id'])) {
$the_post_id = $_GET['p_id'];
$the_post_author = $_GET['author'];
}
if(isset($_POST['delete_sub'])) {
$username = $_SESSION['username'];
$query = "SELECT user_subs FROM users WHERE username = '{$username}' ";
$select_users_by_id = mysqli_query($connection, $query);
while ($row = mysqli_fetch_array($select_users_by_id)) {
$user_subs = explode(',', $row['user_subs']);
foreach($user_subs as $out) {
$query = "UPDATE users SET user_subs = null WHERE username = '{$the_post_author}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
}
}
THIS IS JUST IN TEST, PREPARED STATEMENTS WILL BE USED BEFORE GOING LIVE
Thank you for your time.
I second the other user's comment about moving this column to a different table. In the meanwhile, if you want to achieve what you are asking for, you can try removing the user name from the column value and update it with the remaining text.
if(isset($_POST['delete_sub'])) {
$username = $_SESSION['username'];
$query = "SELECT user_subs FROM users WHERE username = '{$username}' ";
$select_users_by_id = mysqli_query($connection, $query);
while ($row = mysqli_fetch_array($select_users_by_id)) {
$user_subs = str_replace($username . ',', '', $row['user_subs']);
$query = "UPDATE users SET user_subs = '{$user_subs}' WHERE username = '{$the_post_author}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
}
OPTION-2
$user_subs = explode(',', $row['user_subs']);
$user_subs_new = [];
foreach($user_subs as $out) {
if ($out !== $username) {
$user_subs_new[] = $out;
}
}
$user_subs = implode(',',user_subs_new);
$query = "UPDATE users SET user_subs = '{$user_subs}' WHERE username = '{$username}' ";
$unsubscribe_user = mysqli_query($connection, $query);
echo "Unsubscribed";
}
Let's start over. Let's start here, in fact...
DROP TABLE IF EXISTS users;
CREATE TABLE users
(user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,email VARCHAR(20) NOT NULL UNIQUE
);
DROP TABLE IF EXISTS user_subs;
CREATE TABLE user_subs
(user_id INT NOT NULL
, sub_id INT NOT NULL
, active TINYINT NOT NULL DEFAULT 1
, PRIMARY KEY(user_id,sub_id)
);
INSERT INTO users VALUES
(1,'b.smyth634#gmail.com'),
(2,'james#gmail.com'),
(3,'f#gmail.com'),
(4,'sally#gmail.com'),
(5,'thomas#gmail.com');
INSERT INTO user_subs (user_id,sub_id) VALUES
(1,5),
(1,2),
(1,1),
(1,4),
(2,1),
(2,2),
(2,4);
SELECT * FROM users;
+---------+----------------------+
| user_id | email |
+---------+----------------------+
| 1 | b.smyth634#gmail.com |
| 2 | james#gmail.com |
| 3 | f#gmail.com |
| 4 | sally#gmail.com |
| 5 | thomas#gmail.com |
+---------+----------------------+
SELECT * FROM user_subs;
+---------+--------+--------+
| user_id | sub_id | active |
+---------+--------+--------+
| 1 | 5 | 1 |
| 1 | 2 | 1 |
| 1 | 1 | 1 |
| 1 | 4 | 1 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 4 | 1 |
+---------+--------+--------+
SELECT u.*
, GROUP_CONCAT(us.sub_id) subs
FROM users u
JOIN user_subs us
ON us.user_id = u.user_id
GROUP
BY u.user_id;
+---------+----------------------+---------+
| user_id | email | subs |
+---------+----------------------+---------+
| 1 | b.smyth634#gmail.com | 1,2,4,5 |
| 2 | james#gmail.com | 1,2,4 |
+---------+----------------------+---------+
From here we have a choice. We can either DELETE subs we no longer wish to consider, or simply UPDATE them as 'inactive'.
Either way, we just need a DELETE or an UPDATE. So no SELECT needed. In fact a SELECT would, as I mentioned, be counterproductive - because a user may modify the data set in between the execution of the SELECT and the execution of the UPDATE/DELETE. This is known as a 'race condition'.

How to implement a PHP condition using pure SQL?

I have this tables structure:
// Posts
+----+------------+-----------------------+----------------+-------------+
| id | title | content | money_amount | author_id |
+----+------------+-----------------------+----------------+-------------+
| 1 | title 1 | content 1 | NULL | 12345 |
| 2 | title 2 | content 2 | 25 | 42355 |
| 3 | title 3 | content 3 | 5 | 53462 |
| 4 | title 4 | content 4 | NULL | 36346 |
| 5 | title 5 | content 5 | 15 | 13322 |
+----+------------+-----------------------+----------------+-------------+
// ^^ NULL means this post is free
// Money
+---------+--------------+
| post_id | user_id_paid |
+---------+--------------+
| 2 | 42355 | // He is author of post
| 2 | 34632 | // This row means besides author, this user 34632 can see this post too. Because he paid the money of this post.
| 3 | 53462 | // He is author of post
| 5 | 13322 | // He is author of post
| 3 | 73425 | // This row means besides author, this user 34632 can see this post too. Because he paid the money of this post.
+---------|--------------+
Note1: All post_id(s) in the Money table are belong to those posts which are non-free.
Note2: Always there is a row belong to author of post (which is non-free) in the Money table.
Note3: Money table is just to determines who can see such a post.
Now this user $_SESSION['current_user'] = '23421' wants to see this post id = 2. Here is my code:
$stm = $this->dbh->prepare(SELECT * FROM Posts WHERE id = '2');
$stm->execute();
$result = $stm->fetch(PDO::FETCH_ASSOC);
if ( $result[money] == '') { // money_amount is NULL in the Posts table
this post is free and everybody can see it
} else {
$stm = $this->dbh->prepare(SELECT count(1) FROM Money WHERE post_id = '2' and user_id = $_SESSION['current_user']);
$num_rows = $stm->fetchColumn();
if($num_rows){
$paid = true; // This means current user paid the cost of post and he can see it.
} else {
$paid = false; // this means current user didn't pay the cost of post and he cannot see it.
}
}
I want to know, can I implement those two query in one query and do that condition using MySQL instead of PHP ?
Here is solution using IF and EXISTS functions(MySql):
...
$stmt = $conn->prepare("
SELECT IF(p.money_amount,1,0) as notfree,
EXISTS(SELECT * FROM `Money` WHERE `post_id` = ? AND`user_id_paid` = ?) as paid
FROM `Posts` p WHERE p.id = ? ");
$stmt->execute([2, $_SESSION['current_user'], 2]);
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
if (!$result['notfree']) { // post is free
// this post is free and everybody can see it
} else {
$paid = ($result['paid'])? true : false;
}
You can use a join, and the query below uses LEFT JOIN.
SELECT * FROM Money
LEFT JOIN Posts ON Money.post_id = Posts.id
WHERE ((Posts.money_amount IS NOT NULL AND Money.user_id_paid = :userId)
OR Posts.money_amount IS NULL) AND Posts.id = :postId
Note that :userId is a placeholder for PDO parameterized query, where you should bind the parameter to the placeholder before execution. Like:
$postId = 2;
$stmt->bindParam('userId', $_SESSION['current_user']);
$stmt->bindParam('postId', $postId);
Also note that when binding the placeholder name doesn't need the colon. Using a RIGHT JOIN means you SELECT from the Posts table and join the Money table.

Zend Framework 1. Fetch comments

I can't create an appropriate query which could select all comments connected with one particular image and get those comments authors.
I would like to create a query something like:
select a comment where comment_id == image_id && user_id(table comments) == user_id(table users)
This is MySQL part:
Table 'comments'
id | comment | user_id | image_id |
1 | test 1 | 1 | 1 |
2 | test 2 | 1 | 2 |
3 | test 3 | 2 | 1 |
Table 'users'
id | name |
1 | test1 |
2 | test2 |
Table 'images'
id | img |
1 | test.jpg |
2 | test.jpg |
3 | test.jpg |
4 | test.jpg |
Controller Part:
$imageId = $filter->filter ($request->getParam('id'));
$this->view->imageId = $filter->filter ($request->getParam('id'));
$this->view->imageChosen = $images->fetchRow($images->select()->where('id = ?', $imageId));
$users = new Users();
$userChosen = new Users();
$comments = new Comments();
$this->view->comments = $comments->fetchAll();
$this->view->userChosen = $users->fetchRow($users->select()->where('id = ?', $this->view->imageChosen->author_id));
$this->view->commentsChosen = $comments->fetchAll($comments->select()->where('id = ?', $imageId));
View part:
for ($i=0; $i < count($this->commentsChosen); $i++) {
echo $this->commentChosen[$i]->comment;
}
Right now I only get the very first comment.
What I mean is I need all comments belonging to each picture as well as authors info.
Thanks for your help!
As you've said, you can fetch the image info with your query, I'll extend it in order to fetch the user info too:
$select = $comments->select()->setIntegrityCheck(false)
->from('comments')
->joinInner('users', 'users.id = comments.user_id')
->where('comments.image_id = ?', $this->view->imageChosen->id);
$this->view->commentsChosen = $comments->fetchAll($select);
The generated query would be:
SELECT comments.* users.* FROM comments
INNER JOIN users ON users.id = comments.user_id
WHERE comments.image_id = [Your_id_here]
I hope this helps!
I've managed to get all comments belonging to each picture.
Controller:
$this->view->commentsChosen = $comments->fetchAll($comments->select()->where('image_id = ?', $this->view->imageChosen->id));
View:
for ($i=0; $i<count($this->commentsChosen); $i++) {
echo $this->commentsChosen[$i]->comment;
//Have 'user_id' only
echo $this->commentsChosen[$i]->user_id;
}
However, I still can't get authors details.

How to increment the search count in php/mysql?

I have a table consists of several fields (id, firstname, surname, username, search_count)
I've build a small search engine that search my table to find any match exists either in the firstname or in the surname and I am getting the results with no problems.
Now, what I am trying to do is to increment the search_count field by 1 every time there is a match!
For example let's say we have the following table users:
id | firstname | surname | username | search_count
1 | John | Mike | un1 | 0
2 | John | Jeff | un2 | 0
3 | Dale | John | un3 | 0
4 | Mike | Gorge | un4 | 0
and let's say we are searching for Jeff as a keyword
so, the query will return 1 record
what I want to do is to increment the search_count by 1 for match record
so the results will be something like as:
id | firstname | surname | username | search_count
2 | John | Jeff | un2 | `1`
and if we make a new search (e.g. John) the results should be something like:
id | firstname | surname | username | search_count
1 | John | Mike | un1 | 1
2 | John | Jeff | un2 | 2
3 | Dale | John | un3 | 1
I've tried several approach but with no luck.. So I appreciate any hints and help
here is my code...
<?php
// open the HTML page
include 'html_open.php';
// require the db connection
require '/inc/db.inc.php';
// require the error messages
require '/inc/echo.inc.php';
if (isset($_GET['keyword'])) {
$keyword = $_GET['keyword'];
if (!empty($keyword)) {
// build our search query
$search_query = "SELECT * FROM `users` WHERE `firstname` = '".mysql_real_escape_string($keyword)."' OR `surname` = '".mysql_real_escape_string($keyword)."' ORDER BY `search_count` DESC";
// run the search query
$search_query_run = mysql_query($search_query);
// search results
$search_results_num = mysql_num_rows($search_query_run);
// check query return results
if ($search_results_num>0) {
echo 'Search engine returns <strong>[ '.$search_results_num.' ]</strong> result(s) for <strong>[ '.$keyword.' ]</strong>:<br>';
// retrieving the information found
echo '<ol>';
while ($search_result_information = mysql_fetch_assoc($search_query_run)) {
//$current_search_count = ;
echo '<li>'.$search_result_information['username'].'. This user has been searched: '.$search_result_information['search_count'].' times before.</li>';
}
echo '</ol><hr>';
include 'search_form.php';
} else {
echo '<hr>Search engine returns no result for <strong>[ '.$keyword.' ]</strong>, please try another keyword.<hr>'; // hint: no result found
include 'search_form.php';
}
} else {
echo $err20_002; // hint: must insert input
include 'search_form.php';
}
} else {
echo $err20_001; // hint: form has not been submitted
include 'search_form.php';
}
// close the HTML page
include 'html_close.php';
?>
P.S. I am new to PHP / MySQL and this is my first code :)
...
while ($search_result_information = mysql_fetch_assoc($search_query_run)) {
# add this following line
mysql_query('UPDATE `users` SET search_count=search_count+1 WHERE id='.$search_result_information['id']);
# Edit. Change result to show new number
$search_result_information['search_count']++; # this adds 1 to the value (does not affect stored data in database)
echo '<li>'.$search_result_information['username'].'. This user has been searched: '.$search_result_information['search_count'].' times before.</li>';
}
...
In your case you need to fetch the found values and perform an update statement adding +1 to the search_count column
$search_query = "SELECT id, firstname, surname, username, search_count FROM `users` WHERE `firstname` = '".mysql_real_escape_string($keyword)."' OR `surname` = '".mysql_real_escape_string($keyword)."' ORDER BY `search_count` DESC";
$search_query_run = mysql_query($search_query);
// search results
$search_results_num = mysql_num_rows($search_query_run);
// check query return results
if ($search_results_num>0) {
echo 'Search engine returns <strong>[ '.$search_results_num.' ]</strong> result(s) for <strong>[ '.$keyword.' ]</strong>:<br>';
// retrieving the information found
echo '<ol>';
while ($search_result_information = mysql_fetch_assoc($search_query_run)) {
//$current_search_count = ;
$update_search = "UPDATE users SET search_count = search_count + 1 WHERE id = {$search_result_information['id']}"; // so every `id` will increment its search_count with 1. You will need to select the rows once again, to take this count, or to manually increment in PHP
mysql_query($update_search);
echo '<li>'.$search_result_information['username'].'. This user has been searched: '.$search_result_information['search_count'].' times before.</li>';
P.S.: Using mysql_* lib is strongly NOT recommended. As you can see from the red box in the official documentation http://www.php.net/manual/en/function.mysql-query.php you should choose one of the current actually supported APIs

What is the correct way to join two tables in SQL?

I have two tables. The first table holds simple user data and has the columns
$username, $text, $image
(this is called "USERDATA").
The second table holds information about which users "follow" other users, which is set up with the columns
$username and $usertheyfollow
(this is called "FOLLOWS").
What I need to do is display the data individually to each user so that it is relevant to them. This means that userABC for instance, needs to be able to view the $text and $image inputs for all of the users whom he/she follows. To do this, I believe I need to write a sql query that involves first checking who the logged in user is (in this case userABC), then selecting all instances of $usertheyfollow on table FOLLOWS that has the corresponding value of "userABC." I then need to go back to my USERDATA table and select $text and $image that has a corresponding value of $usertheyfollow. Then I can just display this using echo command or the like...
How would I write this SQL query? And am I even going about the database architecture the right way?
With tables like so:
userdata table
______________________________
| id | username | text | image |
|------------------------------|
| 1 | jam | text | image |
+------------------------------+
| 2 | sarah | text | image |
+------------------------------+
| 3 | tom | text | image |
+------------------------------+
follows table
_____________________
| userId | userFollow |
|---------------------|
| 1 | 2 |
+---------------------+
| 1 | 3 |
+---------------------+
and use the following SQL:
SELECT userdata.text, userdata.image FROM follows LEFT JOIN userdata ON follows.userFollow = userdata.id WHERE follows.userId = 1
will get all the text and images that user with id '1' follows
As it turns out, neither of these answers were right. #jam6459 was closest.
The correct answer is the following:
SELECT userdata.text, userdata.image, follows.userFollow
FROM userdata
LEFT JOIN follows ON follows.userFollow = userdata.username
WHERE follows.userId = $username
I also found it easier to not have a username correspond to an Id as in jam's table example. This is because the same user can have multiple entries in "USERDATA". I instead used username as the Id.
function get_text_image($username)
{
$sql = "SELECT * FROM USERDATA where username='".$username."'";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
echo $row['text'];
echo $row['image'];
}
}
function display_data_of_followers($userid)
{
$sql = "SELECT usertheyfollow FROM follow WHERE userid = ".$userid."";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result))
{
get_text_image($row['usertheyfollow']);
}
}
display_data_of_followers($userid);

Categories