Making php script run multiple times - php

I have a system where a PHP script uses MySQL to get info based on a user. Then, based on that information, a certain button will be displayed. The database that is being called has columns:
id
user_one
user_two
This is meant to check if two users are friends. However, my problem is that if a user has more that 1 friend the script only works for the 1st friend.
$select_friends_query = mysql_query("SELECT friend_id FROM friends WHERE user_id = '$user'");
while($friend_row = mysql_fetch_assoc($select_friends_query)) {
$friend = $friend_row['friend_id'];
}
if ($username == $friend) {
$addAsFriend = '<input type="submit" class = "frnd_req" name="removefriend" value="Disassociate">';
}
else
{
$addAsFriend = '<input type = "submit" class = "frnd_req" name = "addfriend" value = "Send Associate Request">';
}
}
}
Then I have echo $addAsFriend later.

I recommend that you change your database design as follows:
User_id, PK
Friend_id, PK
PK = Primary Key. Primary key is the key under which records are stored. It must be unique. The reason we are making it a COMPOUND primary key (two fields make up the PK instead of 1) is because it is impossible for a user to be friends with with the same user Multiple times. Mysql will ensure this does not happen and you won't have to do it on the application level.
Thus, if user "12" and user "25" become friend you should two records:
(12, 25) and (25, 12)
You must have two records because data means literally "user this has friend that." Is it possible for two users to have a one way friendship - not really BUT you may want to one day expand this table to include preferences on the relationship type between the two friends and you would want to distinguish between A -> B and B -> A relationship.
So let's get to the meat of the question. To query mysql to find all friends to a specific user we do the following:
$sql = "SELECT friend_id FROM friends WHERE user_id = 25;";
$query = mysql_query($sql, $connection);
// Loop through all friend records
while ($row = mysql_fetch_assoc($query)) {
$friends[$row['friend']];
}
I don't use procedural code (mysql_query) and instead use mysqli with OP: $mysql->query(). basically, I am not 100% sure if this code will run but it gives you a guide to get started.
At the end of the program, you will have an array "friends" with keys that tell you the friend ids. So "friends" -> 12, 21 could be a potential data set.

You have to look over all results. Like the while loop example in http://www.php.net/manual/en/function.mysql-fetch-assoc.php

Related

Like system In Php

Hey I want to create like system in php But I am facing some problem on it ...
How can I create Like system that allow only one like per one user??
This is my code
<?php
if(isset($_POST['like'])){
$q = "SELECT * FROM likes WHERE `username` = '".$_SESSION['recieveruser']."'";
$r = mysqli_query($con, $q);
$count = mysqli_num_rows($r);
if ($count == "0") {
$q1 = "INSERT INTO likes (`username`, `likecount`)VALUES('".$_SESSION['recieveruser']."', '1')";
$result1 = mysqli_query($con, $q1);
} else {
while($row = mysqli_fetch_array($r)) {
$liked = $row['likecount'];
}
$likeus = ++$liked;
$q2 = "UPDATE likes SET likecount='".$likeus."' WHERE username = '".$_SESSION['recieveruser']."'";
$result2 = mysqli_query($con, $q2);
}
}
give me some suggestions
I want only one like per user
In this code every user can give Many likes to another user but I want only one like per one user and I want to display the name of the user who gave like if it's possible
This is only user like code...
I created simliar like system on my website. In my likes table, I had these columns:
Id of comment, that has been liked
Id of user who liked
Id of like (for removal)
When user clicked like, I inserted new row into likes table, with two known values. ID of like was autoincremented.
To show number of likes, I filtered by id of comment and grouped by users id (just to be sure). The number was obtained using count.
select count(*) from likes where comment_id = 666 group by user_id;
Even if you let user insert multiple times, the like counts only as one. But best would be to check, if current user already liked and dont let him do that. For this task, insert on duplicate key update could be used, to spare if exists db request (select).
You should not use the code you posted above. First of all, your code is vulnerable to SQL-Injections and therefore you should use Prepared Statements (https://www.php.net/manual/de/mysqli.quickstart.prepared-statements.php). Second, $_SESSION variables are depricated (https://www.php.net/manual/en/reserved.variables.session.php).
Lets assume you want users only to be able to like a post once. Then, instead of the column likecount you would need a post-id which uniquely identifies the post.
Define the combination post-id and username as a primary key in your database.
Now your code just have to check whether you find the username with the according post-id in the table likes.
In case you do not find the username with the according post-id in the table, you have to INSERT the username and the post-id

Many to many relationships - Moving data from many tables to a single table

I have a table with users and one with labels
A label can have many users and a user can have many labels, so a Many to Many relationship
A joining table is needed, that's why I have label_user
Below you can see pictures of what they contain with example data:
Users:
https://i.stack.imgur.com/E5E6O.png
Labels:
https://i.stack.imgur.com/1NFjq.png
label_user:
https://i.stack.imgur.com/tW2Uo.png
Let's say I have 5000 users and I can sort them by gender. Let's say 2800 of them are males, how can I assign them all to a label?
Here's some things I tried:
public function add_users_to_label($label_id, $condition, $value)
{
$db = new Database();
$conn = $db->db_connect();
$label_id = escape_string($conn, $label_id);
$query = $conn->query("INSERT INTO `label_user`(`label_id`, `user_id`) SELECT :label_id, psid FROM `iris_messenger_users` WHERE $condition = $value");
$query->bind_param("iss", $label_id, $condition, $value);
if ($query->execute()) {
return true;
}
else {
return "Error inserting data: " . $conn->error . "\n";
}
}
On the user side I have a simple form with select that let's you select a label and then this code:
if(isset($_POST['label-select'])) {
if ($_GET['show_only_gender'] == 'male') {
$condition = 'gender';
$user->add_users_to_label($_POST['label-select'], $condition, $_GET['show_only_gender']);
}
}
Basically, I want to get all users that are male and assign them to a label and put that into label_user with respectively the label_id and the user_id(psid)
Even if this worked I'd still have to do it 2699 times more. What can I do here to optimize and make it to run with 1 query if possible?
I don't think using foreach and running it as much times as there are users is the best option, is it?
Is there any better approach I can take to make this possible?
Although what you are describing does not make sense to have a "label" associated with a person for this specific component, the gender is already on the user table you should be able to get all male based on
select * from user where gender = 'male'
no need to JOIN to a label table on this field. Similarly if you were trying to find people based on a name starting with something... you would not create a label for the name either. Query directly from the table that has that specific component association.
Now, to answer your question, how to insert into the label table for each instance in bulk, you could do something like... I am doing this based on some label ID = 123 as just an example in your labels table that represents gender.
I am doing a LEFT-JOIN in the select so we dont try to add for any user IDs that are already on file do not try to get re-added.
insert into label_user
( label_id,
user_id )
select
123 as label_id,
U.id as user_id
from
users U
left join label_user LU
on U.id = LU.user_id
AND LU.label_id = 123
where
U.gender = 'male'
AND LU.user_id IS NULL
You obviously need to adjust for php.

Check if a value exists in mysql column

Is there a way to check if a value exists in a mysql column? I have table songs, and there are some columns, one of them is called 'agent_ip' where i will put a list/array of all user ip's that will visit the site. I need to check if current user ip is present in column 'agent_ip'. Here is some of my code:
public function voteSong($song_id, $case, $agent_ip) {
$query = $this->link->prepare("SELECT * FROM songs WHERE id = ? LIMIT 1");
$query->bindValue(1, $song_id);
$query->execute();
$rowcount = $query->rowCount();
if ($rowcount != 0)
{
if (!in_array($agent_ip, $r['ip']))
{
if ($case === 'like')
{
while($r = $query->fetch())
{
$vote = $r['votes'] + 1;
}
}
elseif ($case === 'dislike')
{
while ($r = $query->fetch())
{
if ($r['votes'] > 0)
{
$vote = $r['votes'] - 1;
}
else
{
$vote = 0;
}
}
}
$query = $this->link->prepare("UPDATE songs SET datetime = ?, votes = ?, agent_ip = ? WHERE id = ?");
$query->execute(array(date("Y-m-d H:i:s"), $vote, $agent_ip, $song_id));
}
}
}
The line if(!in_array($agent_ip, $r['ip'])) contains the wrong function which won't work, but i need an alternative for mysql. $r['ip'] variable is data from the 'agent_ip' column which look like this 127.0.0.1, 127.0.0.1, 127.0.0.1 (using 127.0.0.1 just for example, every 127.0.0.1 is a different ip)
If you're only checking against a single IP, why don't you just modify your query from:
"SELECT * FROM songs WHERE id = ? LIMIT 1"
To:
"SELECT * FROM songs WHERE id = ? AND agent_ip = ? LIMIT 1"
It seems a bit wasteful to query your whole result set when you are only querying against a specific IP and returning a single row.
EDIT: Your current method would be extremely inefficient, you are passing a unique agent_ip each time you want to query a song to check if the IP exists, that would be fine, but you are creating a new DB connection every time from which you pull back all info which belongs to that song.
Lets say we have 1 song, and 3IP's, currently the application would work like this:
1) Call the method, passing IP_1
2) Query the database getting all songs for ID1
3) Check if IP_1 is in the result set and do process
4) Call the method, passing IP_2
5) Query the database getting all songs for ID1
6) Check if IP_2 is in the result set and do process
7) Call the method, passing IP_3
8) Query the database getting all songs for ID1
9) Check if IP_2 is in the result set and do process
As you can see, there is a lot of repetition here which is going to hinder your apps performance as it scales, you would be so much better modifying your current function to accept a list of results for a song which is pre-queried only once and then recursively call a check function by passing that result array with your unique IP address.
UPDATE You stated I understand that i need to have 2 tables(1 = songs; 2 = votes). But i cannot imagine how i will get songs from database, arranged by votes quantity.
You should read SQL's JOIN documentation, the concept is simple - JOIN allows you to pull back a more detailed set of information based on what you want to query, in your example you may want to find out how many votes a specific song has.
Your tables may look like:
Songs
SONG_ID Primary Key
SONG_TITLE
SONG_DURATION
SONG_TAGS
Votes
VOTE_ID Primary Key
SONG_ID Foreign Key - (references the song_id table)
VOTE_RES Bool (either 0 for no, 1 for yes)
AGENT_IP Who sent the vote
You could then find out how many people said they liked the song by performing a join:
SELECT * FROM songs
JOIN votes
ON songs.song_id = votes.song_id
WHERE songs.song_id = 1
AND votes.vote_res = 1;
This would return all the song with the id of 1 and all of its associated likes. Hope that helps a bit :)
First you need to deserialize/decode the data from the column to the proper php array and then you can use in_array function. In your post edit you stated that you have a comma separated list of IP's, so to convert it to array you need to use an explode function:
$ip_list = explode(', ', $r['ip']);
now you can use the in_array function on the new array:
if(!in_array($agent_ip, $ip_list))

database trouble - same values in different rows

I am trying to make my voting system work. I have 3 databse tables:
users, posts, votes
the table users has field username as the primary key. table post has post_id as the primary key. (there are more fields but they don't affect the question/problem)
In the votes table I have 3 fields: username, post_id, vote. vote is enum ('positive', 'negative'). What I'm trying to achieve is that if a user votes for a specific post that is displayed on a page, the query: INSERT INTO votes ('username','post_id','vote') VALUES('$user_name','$post_id', 'positive'); will be executed.
It works if lets say user 123123 has not voted for any post at all yet. When this user votes lets say for post 1, this query works fine. But then if this user wants to vote for a different post, (his vote gets counted - I just copied the part of the code that doesn't work, the rest of it is fine and working) the insert query get's not executed. If user abcd wants to vote for a specific post, this works fine again, but only once. It seems to me that there is some kind of problem with the database, so that there can be only one entry with the same username or post_id. How can I fix this if I want one user to be able to vote for multiple posts? Is there a better strategy for this?
if($runloggedin->num_rows == 1)
{
// If there was no vote for the current posting, then execute this query
$query = "SELECT * FROM posts WHERE post_id='".$post_id."' AND user_name='".$user_name."'"; //get username and the post id
$result = $mysqli->query($query);
$query1 = "SELECT * FROM votes WHERE post_id='".$post_id."' AND username='".$user_name."'"; //check if there is a vote for this post already
$result1 = $mysqli->query($query1);
if ($result->num_rows == 1 && $result1->num_rows == 0)
{
$vote = "INSERT INTO votes ('username','post_id','vote') VALUES('$user_name','$post_id', 'positive')"; // this isn't working. everything else seems to be working (still test it more)
$savevote = $mysqli->query($vote);
$addvote = "UPDATE posts SET posvotes=posvotes+1 WHERE post_id='".$post_id."'";
$runvote = $mysqli->query($addvote);
echo "Thank you for your vote";
}
}
Without seeing how your votes table was created, my guess is that username has been set up as the primary key. This will make the first INSERT work, but all future ones fail. What you need to do is change it to have username & post_id be the primary key
ALTER TABLE `votes` DROP PRIMARY KEY , ADD PRIMARY KEY ( `username`, `post_id` )

sql using LIKE clause : php

I'm trying to generate a list of events that a user is attending. All I'm trying to do is search through columns and comparing the userid to the names stored in each column using LIKE.
Right now I have two different events stored in my database for testing, each with a unique eventID. The userid i'm signed in with is attending both of these events, however it's only displaying the eventID1 twice instead of eventID1 and eventID2.
The usernames are stored in a column called acceptedInvites separated by "~". So right now it shows "1~2" for the userid's attending. Can I just use %like% to pull these events?
$userid = $_SESSION['userid'];
echo "<h2>My Events</h2>";
$myEvents = mysql_query("select eventID from events where acceptedInvites LIKE '%$userid%' ");
$fetch = mysql_fetch_array($myEvents);
foreach($fetch as $eventsAttending){
echo $eventsAttending['eventID'];
}
My output is just 11 when it should be 12
Change your table setup, into a many-to-many setup (many users can attend one event, and one user can attend many events):
users
- id (pk, ai)
- name
- embarrassing_personal_habits
events
- id (pk, ai)
- location
- start_time
users_to_events
- user_id ]-|
|- Joint pk
- event id ]-|
Now you just use joins:
SELECT u.*
FROM users u
JOIN users_to_events u2e
ON u.id = u2e.id
JOIN events e
ON u2e.event_id = e.id
WHERE u.id = 11
I'm a bit confused by your description, but I think the issue is that mysql_fetch_array just returns one row at a time and your code is currently set up in a way that seems to assume $fetch is filled with an array of all the results. You need to continuously be calling mysql_fetch_array for that to happen.
Instead of
$fetch = mysql_fetch_array($myEvents);
foreach($fetch as $eventsAttending){
echo $eventsAttending['eventID'];
}
You could have
while ($row = mysql_fetch_array($myEvents)) {
echo $row['eventID'];
}
This would cycle through the various rows of events in the table.
Instead of using foreach(), use while() like this:
$myEvents = mysql_query("SELECT `eventID` FROM `events` WHERE `acceptedInvites` LIKE '".$userid."'");
while ($fetch = mysql_fetch_array($myEvents))
{
echo $fetch['eventID'];
}
It will create a loop like foreach() but simpler...
P.S. When you make a MySQL Query, use backticks [ ` ] to ensure that the string is not confused with MySQL functions (LIKE,SELECT, etc.).

Categories