Twitter-like following system - php

I am working on a twitter clone in PHP for school, and I have one major problem. I cannot find a way to implement a follower system. There is a table for users, and I want to add a field that holds the ids of all of the users that each user follows.
Should I separate the ids with commas and then split them apart in PHP? And then I need to select all of the tweets from the tweets table that were tweeted by any of the users followers. Is there an SQL command that I can use? Something similar to
SELECT *
FROM tweets
WHERE author='$followeduser'"
but where $followeduser is multiple ids.

Have a USER_MASTER table like this
USER_ID (int)
USER_NAME(varchar(50))
Create a table called USER_FOLLOWERS like this
USER_FOLLOWER_ID // Auto increment-Primary Key for this record
USER_ID (int) // foriegn key to UserId column in USER_MASTER table
FOLLOWER_ID (int) // foriegn key to UserId column in USER_MASTER table
Store the UserId in the first column and store the UserId of the User who follows this user in the Follower_ID column.
So your data will look like this
USER_ID USER_NAME
--------------------------------------
1 SCOTT
2 JARED
3 MARC
4 ERIC
USER_FOLLOWER_ID USER_ID FOLLOWER_ID
--------------------------------------
1 1 2
2 1 3
3 1 4
4 2 1
So this means , The User Scott has 3 followers, Jared, Marc and Eric. User JARED HAS one Follower, that is SCOTT
To get the list of Followers for a user(ex : Scott (ID=1)) , you can do a Join between these 2 tables
SELECT U. USER_ID, U.USER_NAME From USER_MASTER U
INNER JOIN USER_FOLLOWERS UF ON U.USER_ID=UF.FOLLOWER_ID
WHERE UF.USER_ID=1 // 1 is the ID of SCott

Make a join table.
Putting all IDs in a list is not the normalized way and can lead to many many issues.

Have a relations table where you have one column called user and second that is following. So if user 1 is following user 3 and 5, then you would have an entree where user = 1 following = 3 and user = 1 following = 5 (use whatever ID's you want). You also have your Tweets Table where you store all tweets. Youre going to want to make a query that joins the two tables

Related

Update two or more table

i have three tables.
1st table is tbl_user
id u_name p_list
1 demo1 1,3,
2 demo2 4,3,1,
3 demo3 2,3,
4 demo4 2,5,
Second table is tbl_product
id product_name
1 example1
2 example2
3 example3
4 example4
5 example5
third table is tbl_order_list that show the list of order to the users. tbl look like
id pid uid
1 1 1,2,
2 4 2,
3 3 1,2,3,
4 5 4,
now i want
if i'll update tbl user means if i'll remove pid of column p_list of tbl_user than tbl_user will be updated and also tbl_order_list is update
"Example" if i'll remove 3 in p_list of id 2 from tbl_user than table is look like
id u_name p_list
1 demo1 1,3,
2 demo2 4,1, //(pid =3 is remove of demo2)
3 demo3 2,3,
4 demo4 2,5,
And tbl_order_list is look like
id pid uid
1 1 1,2,
2 4 2,
3 3 1,3, //(uid =2 is remove)
4 5 4,
what is the solution of this problem. i want also if i'll add again pid = 3 in p_list of id = 2 of table user than table look like previous tables.
QUERY (From Comments)
mysql_query("UPDATE tbl_user SET u_name='$userName',slug='$userSlug',password='$userPassword',email='$use‌​rEmail',role='$userRole',p_list='$userList',status='$userStatus',modified_‌​date='$userDate' WHERE id='$uId'");
Help Me
So far, I'm not seeing any real correlation to php, but whatever.
I would highly suggest using a normal form (see database normalization) and deduplicate your data. tbl_order_list is a very bad table, as is tbl_user. tbl_order_list shouldn't have an id field, the uid field should contain exactly one uid and the primary key should be (pid,uid) (so both fields). By that point it should be called tbl_order. If you want a list of all pids for a uid or all uids for a pid - at some point - you can query like this:
SELECT GROUP_CONCAT(uid)
FROM tbl_order
WHERE pid=[your pid of interest]
GROUP BY pid
and vice-versa (replace uid with pid and pid with uid). If you want to query it at the same time with the rest of your userdata:
SELECT u.*, GROUP_CONCAT(o.pid)
FROM tbl_user u
LEFT JOIN tbl_order o ON (u.id=o.uid)
[WHERE u.id=[your uid of interest]]
GROUP BY u.id
(and similarly with the tbl_product).
When using mysql >= 5.7 you can create a view:
CREATE VIEW tbl_order_list AS SELECT pid, GROUP_CONCAT(uid) FROM tbl_order GROUP BY pid.
Adding or Removing an order then would result in deleting/inserting a row in tbl_order.
Summary: Make a table tbl_order (uid,pid) that contains the links between uids and pids (one link per row). Join this table in, when you need the the links. Please don't save "references" as a comma-separated list in a string field unless there is a very very very good reason.
If you infact have a very very good reason, consider adding comma (,) to the beginning and end of your lists, meaning. So:
id pid uid
1 1 ,1,2,
2 4 ,2,
3 3 ,1,2,3,
4 5 ,4,
This way you can safely search, add, remove entries:
SELECT * FROM tbl_order_list WHERE uid LIKE '%,[uid of interest],%'
UPDATE tbl_order_list SET uid=CONCAT(uid,',',[uid to add]) WHERE id=[order to update]
UPDATE tbl_order_list SET uid=REPLACE(",[uid to remove],",",",uid) WHERE id=[order to update]
(and similar for your tbl_user, if you're querying by pid in the tbl_order list, drop the id field.)
If you don't prepend a comma, you might at some point have some problems with consistency.
Anyway, I cannot stress this enough: normalize your database structure unless you have very good reasons not to (and be absolutely sure, they really are good reasons, because usually they aren't)

Best method for storing multiple ID's in MySQL for querying large result sets

I would like to save which email lists a client subscribes to. I might have:
email_lists:
ID Name
1 Coupons
2 Monthly Newsletter
3 Company News
Now, users can subscribe to as many lists as they want. So let's say I have three users:
users:
ID Name Lists
1 Bob 1,3
2 Jane 2,3
3 Tom 1
Now I need to do a query to get all user ID's which are subscribed to list #1:
SELECT ID FROM users WHERE Lists LIKE '%1%'
Is there a better way of storing the list ID's for each user where queries can be performed more efficiently?
A third table subscrib would be the best here:
UserId ListId
1 1 // Bob, Coupons
1 3 // Bob, Company news
2 2 // Jane, Monthly Newsletter
2 3 // Jane, Company news
3 1 // Tom, Coupons
And then your query would be something like (for Company news):
SELECT UserId FROM subscrib WHERE ListId = '3';
Or
SELECT s.ListId, u.Email, u.Name FROM subscrib s
LEFT OUTER JOIN users u ON u.ID = s.UserId
WHERE s.ListId = '3';

Exclude results in Mysql, NOT IN

I need help to write an SQL but i have no idea in this case how.
Tried many different options but nonthing worked.
I have 2 tables in my mysql database
users (id, name, lastname)
blocked_users (id, user_id, blocked_id)
users table
id name lastname
1 nick james
2 james dean
3 mike bendon
blocked_users table
id user_id blocked_id
1 2 1
2 2 3
Example:
What i would like to do is display all users in users table but exclude in this case
those which are blocked by user_id 2.
So if i'm example logged in as Mike Bendon (id 3 in users table)
i should not be able to se james dean (id 2 in users table) because he has blocked me.
Not sure of how to run that with php, but I think this SQL should do what you asked:
SELECT *
FROM users
WHERE id NOT IN
(SELECT user_id FROM blocked_users WHERE blocked_id = $logged_id);
Edit after comment:
Sorry, I misread the id column name. Should be fixed now.
Try this query:
SELECT *
FROM users
WHERE id NOT IN (
SELECT user_id
FROM blocked_users
WHERE blocked_id=$current_user_id);

Return all users from group(s) specified as comma delimited value

I have the following two table scenario:
users
id groups
1 1,2,3
2 2,3
3 1,3
4 3
and
groups
id
1
2
3
How do I return the IDs of all users that belong to group 2 and 1 for example? Should I look into join, a helper group_membership table or function to separate the comma delimited group IDs to get something like this:
group_membership
user_id group_id
1 1
1 2
1 3
2 2
2 3
... ...
You should be having a many-to-many relationship between users and groups, (meaning, a user may belong into multiple groups, and a group can hold multiple users).
You do that by having 3 tables:
users - to describe user information.
groups - to describe group information.
user_groups - to describe which users are in which groups.
In the user_groups, you should have only 2 columns, user_id and group_id, each row is a single user belonging in a single group, where repititions on both sides are allowed.
Your example translates into:
user_id group_id
1 1
1 2
1 3
2 2
2 3
3 1
3 3
4 3
Then, it's very easy to query all of the users in specific groups, as well as all of the groups as user is in.
This process is also called Database Normalization
The possible solution to your problem is a rearranging of your data.
For this, you need three tables. The users, the groups, and a 'link'-table.
users:
user_id
userdata1
groups:
group_id
groupdata1
link
user_id
group_id
In the link list, you create one dataset for each connection.
So, if user 1 is in groups 2 and 3, the link table will have two entries with the user_id 1. One linking to group_id 2, and one linking to group_id 3.
To get back to your example, the query to get all users from group 2 is:
SELECT * FROM users, link WHERE link.user_id = users.user_id AND (group_id = 2 OR group_id = 3);
This will output all the users, who are in one of the groups, some as duplicates (those, who are members of both groups). If you want to avoid duplicates, add 'GROUP BY user_id'
Except a proper normalisation, the only usable hack, and it is a hack, in this situation is using a hack with LIKE.
This is still a slow and horrible practice.
SQL:
SELECT id FROM users
WHERE
groups LIKE '%,$group_id,%'
OR groups LIKE '%,$group_id'
OR groups LIKE '$group_id,%'
You can use the FIND_IN_SET() MySQL function.

Get users position between friends

I'm trying to get a users position between the users friends, but I don't have any idea of how I can do this...
I have two tables.
Table 1: friends (where all the users friends are listed)
Table 2: users (where all the users are listed)
I want the query to check the users position between his friends.
So if I, for example have ID 1 (with 100 credits) and a friend with ID 2 (with 21 credits), the query would list my position as 1.
You don't really provide much information on your table layout, so it's going to be impossible for me to provide a very specific example. I'm also afraid I don't really understand your question, but I'll give it a shot...
First, I'll assume your users table has at least these columns:
id (PK)
credits
And that the friends table has these columns:
user (FK to users.id)
friend (FK to users.id)
Now, if I understand your question, you want to rank all of a user's friends, based on how many credits they have, so:
SELECT u.id,u.credits
FROM friends AS f
JOIN users AS us ON f.friend = u.id
WHERE f.user = 1
ORDER BY u.credits DESC;
in order to get the position I would recommend using PHP for this and not try to put it all in one query. So get a sorted list like Flimzy described and get the position by using an array function like array_search.

Categories