Database table structure for user albums and photos - php

Okay i'm creating a little community website. A user joins my site and he has the option to
enter his informations upload photos add friends and post to his wall. By now i want to know how to implement the album table.
The album has the following attributes:
albumID
albumName
albumCover
albumDescription
albumDate
albumPrivacy enum
userID
username
Now i want to know how to link albums table with the users table. Every user has its ID and username. The usersId is primary key and the username is unique.
1 user can have many albums. 1 album can belong to only 1 user.
How can i do relationships ???
Help please because im not that good at databases and i want to get things done in optimized and secured way.
By now i use usersid and username as attributes in albums table to identify which album belongs to who. like this SELECT * FROM albums WHERE userid='$userid' AND username ='$username'. Where $userid is value from session variable and $username is value from session variable.

Is username in the Users table? If so, then you don't need to worry about including it in the Albums table, too.
The usersId is primary key and the username is unique.
Just to clarify, the userID should be a primary key on the Users table, but a foreign key on the Albums table (as matthewh mentioned). "albumID" is the column that should be the primary key for the Albums table.
Your SELECT SQL can also be simplified, as you should not need username in your WHERE clause. I'm going to assume that users can't have multiple usernames, so only stating userID in your WHERE should be sufficient.
However, if you still want to see username in your Albums result set, you can do this:
SELECT a.*, u.username
FROM albums a
INNER JOIN users u ON u.userid = a.userid
WHERE a.userid='$userid';
Also I feel compelled to mention that you should really parameterize your SQL statement (in your PHP code) instead of concatenating your SQL command string together. That will protect it from SQL injection attacks. It's a bigger danger with user input, so using a session variable should be ok. But it's still a good habit to get into.

The way you've done it is pretty much right. You only need to have the userID column in the album table, because it is a primary key in the user table and thus guaranteed to be unique. Having the username column in the album table is redundant.
You just need to make sure the userID column in the album table is defined as a FOREIGN KEY and of course has an index applied to it.

Related

Linking SQL Tables - Issue

I would like to link two SQL tables together, both the tables have data entered in them through HTML/PHP forms.
The first table is where the user enters all their details into a form (called system), and the second table is for where a user fills out another form for booking (called users). How do I link these tables together? To show the users booking(s).
I don't know how to get the booking table/form to echo out the user's username into the second table to link them together?
I understand that this does not make sense but would really appreciate some help!!!
Here is the first table's SQL for creating a user account:
And, here is the SQL for creating a booking?:
</form>
</body>
</html>
<br></br>
</div>
</div>
</div>
</body>
</html>
Here is the code that links what the user entered for the booking form (system table) to the SQL database.
Two tables can be "linked" together using JOIN. If you want to list the bookings (rows in the details table), with some user information, you can use LEFT OUTER JOIN or INNER JOIN. (The difference is that with LEFT OUTER JOIN you get all the bookings even if some of them don't have a user. With INNER JOIN you get only the bookings where there exists a corresponding row in users.)
If a column has the same name in two different tables, you can use users.user_uid and details.user_uid to refer to them.
SELECT details.*, user.email, user.first, user.last
FROM details LEFT OUTER JOIN user ON user.user_id = details.user_uid;
Then you maybe want to add a WHERE or ORDER BY and perhaps a LIMIT.
In the users table, there is a user_id (INT) and a user_uid (VARCHAR). The details table has a user_uid (INT). In the example, I was assuming that the user_uid in the details table corresponds to the user_id in the users table because these are both INT. You might want to change the name of some column to make it less confusing. Let's assume you want to rename users.user_uid to "username".
Also, you should add a unique index on the user_id and username, assuming that you want both of them to be unique. For the INT, I suggest you make this the primary key with automatically incrementing numbers and the username, just a unique key:
CREATE TABLE users (
user_id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
... ,
username VARCHAR(20) NOT NULL UNIQUE,
...
);
In the details table you probably also want to make the ID a PRIMARY KEY with AUTO_INCREMENT.
A unique key guarantees that there are no duplicates and it also makes lookups on these columns efficient.
If you are just trying to query them together a join should do the trick.
SELECT users.user_first, users.user_last, users.user_email, system.* FROM system INNER users JOIN ON users.user_uid = system.user_uid
In order to store the user_uid value in the system table you need to add a hidden input in your form like this:
<input type="hidden" name="uid" value="<?php echo $_SESSION['u_id']; ?>">
then in your php add
$user_uid = $_POST['uid'];
and insert it when you run your insert query.
INSERT INTO system (date, time, table_layout, user_uid) VALUES ('$date', '$time', '$table_layout', '$user_uid');
Just make sure that your table actually has that column. Once that value is available you should be able to run the above join query.
Let's see. You have two tables, one with user data (users), and one with booking data (details). A "details" row contains an ID of the user linked to that particular row.
Once you know, at least, the ID of the booking, you can get the id of the user like this:
SELECT user_uid FROM details WHERE ID = #specificBookingID
Once you know the user id you can get the user data:
SELECT * FROM users where user_uid = #retrievedUserID
You can do it in one query like so:
SELECT * FROM users where user_uid IN (SELECT user_uid FROM details WHERE ID = #specificBookingID)

Simple MYSQL data query?

Just a really simple question. In my SQL database I have a column named "friend_count" in table "users" to record all friends the logged in user has. This works with UserID numbers and I am trying to figure out how to record them all. Here's my example:
USER #29 becomes friends with USER #422
In the user database under USER #29's info in the column "friend_count" there will then be the number "422", if he then becomes friends with USER #500, it will show "422, 500" and so on... If he deletes one, that particular number is removed from the box. The script will then search these numbers through the user database to show a list of the people you are friends with.
How can I do this? Any ideas? Thanks!
Any time you have a delimited list of values in a column it's almost always a sign that the data model is incorrect. (Actually, I can't think of an exception to this, but I'll stick with "almost always" just to be safe.)
In this case you have two types of entities:
User
Friendship
A friendship, though not a physical object, is a conceptual entity in and of itself. It connects two users and can add more information related to the friendship itself but not necessarily to the two users.
So you might have tables like this:
User
--------
ID
Name
etc.
Friendship
--------
ID
OriginatingUser
AcceptingUser
BecameFriendsOn
etc.
So OriginatingUser might be the user who sent the friend request, and AcceptingUser might be the user who accepted it. BecameFriendsOn is the date it was accepted. You'd probably want to have statuses and other dates to keep track of pending requests, denied requests, etc. But all of this information is related to the friendship, not necessarily to the users.
The concept you're looking to understand here is called a Foreign Key. The OriginatingUser and AcceptingUser columns are the same data type as the ID column on the User table. You would create the Friendship table such that those columns are foreign keys to the User table, this enforces the integrity of the data so that you can't create a Friendship record without two valid and existing User records.
Then to get the list of friends, you'd join the tables in a query. Perhaps something like this:
SELECT
User.Name
FROM
Friendship
INNER JOIN User ON Friendship.AcceptingUser = User.ID
WHERE
Friendship.OriginatingUser = ?
When supplied with the ID of the originating user, this would get all of the names of users to whom that user sent a friend request. You can further build on the query to also get users who sent this same user a friend request, and so on. By making use of the key foreign key relationships between tables which represent different types of entities in the system, you can construct very robust queries to view that data in lots of different ways.
You are describing a relationship between two entities so you can create a table to store the details of that relationship.
Suppose that you have your user table with a userid column and other columns. You can then create a friends table with two columns that are both foreign keys to the user table.
friends = (user, friend)
Thus, for each friend that user #29 gets you need to add a row into the friends table. For example:
USER
ID NAME ...
29 Sam
30 Henry
32 Jane
Friends
user friend
29 30
29 32
Sam is friends with both Jane and Henry but Jane and Henry are not friends.
I would create a table "friendship" with two cols "user" and "friend", then you start adding pairs of user/friend ids
users table:
id, username, whatever else
friends table:
relationship_id, user_id, user_friend_id
example query to get a list of IDs that belong to the users friends:
SELECT f.user_friend_id FROM users u
LEFT JOIN friends f ON f.user_id = u.id
WHERE u.id = {$user_id}
A very simple approach, assuming that if UserA becomes friends with UserB , then UserB also becomes friends with UserA.
Usually, Comma Separated Lists are not recommended, as they will become a pain when the list is very large. A simpler approach will be, make a table friends with columns user_id and friend_id Where user_id and friend_id are the respective UserIDs .
Now when you want to add a friend to someone's list, use the following :
INSERT INTO users (user_id,friend_id) VALUES(UserA,UserB),(UserB,UserA)
Now when you execute the above query, you will have 2 new rows in your friends table :
user_id friend_id
UserA UserB
UserB UserA
When you want to get the list of a user's friends, use :
SELECT friend_id FROM friends WHERE user_id=(Your user's ID)
This will return a row one by one, and hence will give you all the IDs of friends of a particular user.
Now when you want to delete a friend, use :
DELETE FROM friends WHERE (user_id,friend_id) IN ((user_id,friend_id),(friend_id,user_id))
This removes both the rows from the table, which means that the relationship between UserA and UserB is deleted, and neither of them is friend of each other.

Likes Button from phpacademy

I have been working on the header recently. Now I'm end up to create some likes button like Facebook do.
I'm following the PHPacademy on Youtube. The one who's called Alex is really awesome to share what his idea is.
The problem is, I can't show the user name and the product name which to be liked
This is my query:
function plus_the_like($meal_id) {
$meal_id = (int)$meal_id;
$user_name = mysql_query("SELECT `fullname` FROM `users` WHERE `user_id` = (".$_SESSION['user_id'].")");
mysql_query("UPDATE `meal` SET `likes_meter` = `likes_meter` + 1 WHERE `meal_id` = $meal_id");
mysql_query("INSERT INTO `likes` (`user_id`,`user_name`, `meal_id`) VALUES (".$_SESSION['user_id'].", $user_name, $meal_id)") or die(mysql_error());
}
I know what I am doing wrong just on my query, but ahh... When I'm using the SQL in MySQL all works so well:
SELECT `fullname` FROM `users` WHERE `user_id` = 1
And that query can show me what is the username with the user_id 1
I hope that I can put that username from users table into likes table
Here is what you should be doing.
You have a users table with the following information
id - this is a unique ID of the user, this should be marked as a primary key. Auto incrementing.
Keep whatever else information you want on the user, possibly name, email, etc.
You have an articles table (or whatever your likes are based off of.
id - this is a unique ID of the article, this should be marked as a primary key. Auto incrementing.
Store whatever information you want on your articles, or your items in a store or whatever it is you want to "like".
You have a likes table.
id - this is a unique ID of the like, this should be marked as a primary key. Auto incrementing.
user_id - this is a unique ID of your user that clicked the like button, should be marked as a foreign key.
article_id - this is a unique ID of your article that was "liked", should be marked as a foreign key.
With this, whenever a user "likes" an article, you would have a query like
INSERT INTO likes (user_id, article_id) VALUES (:userID, :articleID);
and to count the number of likes on a given article, you would do something like
SELECT count (user_id) FROM likes WHERE article_id = :articleID;
This will allow you to track how many likes for each article, as well as what each user liked. Potentially, you could eventually suggest things to users based on what they have liked. Though, that is a lot more work to do.
This is a very basic version of what you are attempting to accomplish. As people in the comments have said, look into properly sanitizing your database input. If nothing else, at least change to my_sqli_* if you do not have PDO access. PDO is the suggested way to go though, if you are not going to use a framework that gives you all of this.

MySQL Search for line in text

in MySQL, I have a row for each user, with a column that contains friends names separated by \n.
eg.
Friend1
Friend2
Friend3
I'd like to be able to quickly search all the users where the Friends field contains Friend2.
I've found FIND_IN_SET but that only works for commas and the data can contains commas and foreign characters.
Obviously searching with regular expressions and the such will be slow. I'm new to the whole cross referencing so I'd love some help on the best way to structure the data so that it can be found quickly.
Thanks in advance.
Edit: Ok, I forgot to mention a point that the data is coming from a
game where friends names are stored locally and there are no links to
another users ID. Thus the strings. Every time they connect I am given
a dump of their friends names which I use in the background to help match games.
The most commonly used structure for this kind of data is usually adding an extra table. I.e.
user
id,
name
email,
e.t.c.
user_friend
user_id
friend_id
Querying this is a matter of querying the tables. I.e.
List all of a users friends names:
SELECT friend_id
FROM user_friend
WHERE user_id = :theUser
Edit: Regarding OPs edit. Just storing the names is possible too. In this case the table structure would become:
user_friend
user_id
friend_name
and the query:
SELECT friend_name
FROM user_friend
WHERE user_id = :theUser
Why are you keeping friend names as text? This will be inefficient to edit uf say a user removes a friend or changes their name. That's another thing, you should store friend names by some auto_increment id key in your database. It's much faster to search for an integer than a string, especially in a very large database. You should set up a friends table which is like
Column 1: connectionid auto_increment key
Column 2: user1id int
Column 3: user2id int
Column 4: date added date
ect...
Then you can search the connection table above for all rows where user is user1id or user2id and get a list of the other users from that.
My database hasn't been filled yet so I can easily change the format and structure in which the data will be stored.
Yes, you need to normalize your database a bit. With current structure, your searches will be quite slow and consume more space.
Check out this wiki for detailed help on normalization.
You can have the friends table and users table separate and link them both by either foreign key constraint or inner joins.
The structure would be:
Users table
id: AUTO_INCRMENT PK
name
other columns
Friends table
id: AUTO_INCREMENT(not required, but good for partitioning)
UserID:
FriendsID
DateAdded
OtherInfo if required.

MySQL table to hold pages that a user likes

How would I set up a table for topics that a user likes? I have a topics tables and a user table (more actually but simplified for a post on here). There is an ever increasing number of topics as they are user generated, how could I allow users to like pages? Would i put the topic's id in the user table or the user's id in the topics table or a create a new likes table? The issue I see is that the number of topics could (potentially) be very large. What could I use to create a system that allows a relationship between a users id and the topics id?
What you could possibly do is a "many to many" table structure
A unique auto incremented id - UINT (10) AUTO_INCREMENT
A feild containing the user id - UINT (10) (or what ever matches your main user_id field)
A field containing the "liked" topic id - UINT (10) (or what ever matches your main topic_id field)
Both user_id and topic_id fields would need to be unique together. That means that there can only be once row for a specific like per user. This makes sure (on the database side), that a user will not be allowed to like a topic more than once.
Getting a users liked topics would look like this -
SELECT * FROM user_likes` WHERE `user_id`=USER_ID
Getting the users per like would look like this -
SELECT * FROM user_likesWHEREtopic_id`=TOPIC_ID
As others have said in their answers and also #trevor in the comments below -
Don't forget to add an index on the userid to support retrieval of user liked topics and a separate index on topic is to support the topics per user query - without these, the queries will get slower as more data is added over time.
One way to do it is to create a new table UserLikedTopics or something similar, in which you have two columns, one to keep the UserId and one to keep the TopicId. For each new topic a user "Likes", you add a new row to the table with the UserId and the TopicId. That way it is easy to keep track of which users likes which topics.
To get whoch topics a certain user like, you simply join the UserLikedTopics with your topics table, and you have a list of all topics a certain user like. You could also make it the other way around and join it on the User table, to get a list of the users that like a certain topic.
You will need a 'likes' table. Something like:
CREATE TABLE `users_likes` (
`user_id` INT(10) UNSIGNED NOT NULL,
`topic_id` INT(10) UNSIGNED NOT NULL,
PRIMARY KEY (`user_id`, `topic_id`),
INDEX `topic_id` (`topic_id`)
)
Create a separate likes table since it's a separate entity,
link the likes table with users & topics table with userid & topicsid as foreign keys in likes table..
It would be good to have a structure like this, later if you dont even want a feature likes, can just remove it without affecting other tables...

Categories