MySQL database table structuring - php

I am working on a user based social network. I am building the site in PHP and I want to use a MySQL database to store user data. I can create databases/tables no problem (I use phpMyAdmin)
I am not sure how many tables are necessary and what would be more practical for my web application. Would it be smart to have many tables? For example, a USERS table. With column names USER_ID, EMAIL, PASSWORD, LAST_LOGIN and then a table named USER_SETTINGS that would hold the account settings for each user, and another table named POSTS with the names and values attributed to a "status update". Or is smart to have everything in one table? What is the best practice?

Definately do NOT keep "everything in one table". You'll likely end up with "many tables", but that sounds bad - basically, you should segment your data based on logical usage.
For instance, if you DID keep posts in the users table - how would that work? What happens when they make a new post - would you add another field? (bad) - or add another item TO a field and separate by a character (bad)...etc. The only real way to do it is to have another table. You should definitely NOT keep posts in the same table as users.
As far as 'profile data' (or whatever you want to call it), I like to keep it separate - some people like to keep it in the users table - matter of preference there.
In your case, I'd suggest something like this:
//users table
id,
email,
password,
last_login,
//...
//profiles table
id,
user_id,
profile,
age,
gender,
//...
//posts table
id,
user_id,
data,
created (datetime),
modified (datetime)

I'm presently building a social networking site as well. DO NOT keep everything in one table. In fact I'd go as far as to say, you CANNOT keep everything in a single table without encountering massive issues fairly immediately.
Where users are concerned, I like to keep passwords in a separate table with a hidden user id junction. Profile data itself depending upon how you wish to enforce data integrity for validation and output may involve tables junctioned to your users table.
I would also keep all posts in a separate table. This is purely from the prospective that you can then query according to user id, then limit to the number of posts, or posts appropriate to whatever you're viewing. Simply put, to have them in the users table is like saying that you are what you write and it is you, rather than saying you're separate yet related objects.

Related

What is the proper way to store user preferences in a database?

I have a MySQL database that stores user emails and news articles that my service provides. I want users to be able to save/bookmark articles they would like to read later.
My plan for accomplishing this was to have a column, in the table where I store the users' emails, that holds comma-delineated strings of unique IDs, where the unique IDs are values assigned to each article as they are added into the database. These articles are stored in a separate table and I use UUID_SHORT() to generate the unique IDs of type BIGINT.
For example, let's say in the table where I store my articles, I have
ArticleID OtherColumn
4419350002044764160 other stuff
4419351050184556544 other stuff
In the table where I store user data, I would have
UserEmail ArticlesSaved OtherColumn
examlple1#email.com 4419350002044764160,4419351050184556544,... other stuff
examlple2#email.com 4419350002044764160,4419351050184556544,... other stuff
to indicate the first two users have saved the articles with IDs 4419350002044764160 and 4419351050184556544.
Is this a proper way to store something like this on a database? If there is a better method, could someone explain it please?
One other option I was thinking of was having a separate table for each user where I can store the IDs of the articles they saved into a column, though the answer for this post that this is not very efficient: Database efficiency - table per user vs. table of users
I would suggest one table for the user and one table his/her bookmarked articles.
USERs
id - int autoincrement
user_email - varchar50
PREFERENCES
id int autoincrement
article_index (datatype that you find accurate according to your structure)
id_user (integer)
This way it will be easy for a user to bookmark and unbookmark an article. Connecting the two tables are done with id in users and id_user in preferences. Make sure that each row in the preferences/bookmarks is one article (don't do anything comma seperated). Doing it this way will save you much time/complications - I promise!
A typical query to fetch a user's bookmarked pages would look something like this.
SELECT u.id,p.article_index,p.id_user FROM users u
LEFT JOIN preferences ON u.id=p.id_user
WHERE u.id='1' //user id goes here, make sure it's an int.. apply appropriate security to your queries.
"Proper" is a squirrely word, but the approach you suggest is pretty flawed. The resulting database no longer satisfies even first normal form, and that predicts practical problems even if you don't immediately see them. Some of the problems you would be likely to encounter are
the number of articles each user can "save" will be limited by the data type of the ArticlesSaved column;
you will have issues around duplicate "saved" article IDs; and
queries about which articles are saved will be more difficult to formulate and will probably run slower; in part because
you cannot meaningfully index the the ArticlesSaved column.
The usual way to model a many-to-many relationship (such as between users and articles) is via a separate table. In this case, such a table would have one row for each (user, saved article) pair.
Saving data in CSV format in a database field is (almost) never a good idea. You should have 3 tables :
1 table describing users with everything concerning directly the user
1 table describing articles with data about it
1 table with 2 columns "userid" and "articleid" linking both. If a user bookmarks 10 articles, this table will have 10 records with a different aticleid each time.

PHP/MySQL Program Outline

I'm currently in the process of creating a website and want to know how you guys think I should go about storing my information.
I'm making a website which allows users to create an account and then enter/log in workout information each day that they can.
Each time they input a log, there are a few pieces of information they must include (ie. the date, the length of their workout, the type of workout, etc.). The website will then be able to supply them with graphs that analyze their data.
I'm coding using php and mysql. My question revolves around how I should store all the data for the website. I know I need a mysql table that will have a column for id, username, email, and password. However, I'm unsure how to store the daily logs.
Should I create an array for each field (ie. workout duration) and use serialize() to store it in the same table as the users? If so, how would I go about updating the array each time a log is inputed? Thanks.
I would suggest to use several tables for this, for example the tables:
site_users
site_workouts
That way you have all user data stored separately. In your workouts table, you would add a new row per record, and include a foreign key (user_ID) that links each row to a user. So you could match a list of workout logs to a single user.
It's your choice but personally I would use 2 sql tables:
User(id, username, email, and password)
Workout(user_id, date, workout_length, workout_type)
This way you can keep adding logs for users and recieve the data when needed.
You keep comptibility with alot of other services.
And process the sql records with php.

Merging 2 table fields and inserting into another field in the same record

I am not sure if what I am trying to do is even possible but, if it is, I am obviously not Googling properly and would appreciate any assistance I can get here, even if it is just a link to an "Idiot Guide".
Okay, at the moment, I have a database table of 150-odd records. Each record contains basic details (name, location, contact information, etc.) and login credentials (UserID, password, et al). These details are captured by the website admins (i.e. no general public registration) after the prospective user has undergone a successful interview process. When a record is created, a 6-char "username prefix" is assigned to the user (e.g. 'UNPREF') and this, along with the auto-incremental UserID (e.g. 125), is used as the username (e.g. UNPREF125) to log into the website. However, the username is not actually stored in the the database. Instead, when a user logs in, the login script splits the provided username and the two chunks are checked against their relevant fields.
In addition to this primary user table, there are a number of other tables which contain additional information (for instance, educational qualifications, work history, etc), which are linked to the user by means of the UserID, as per the primary table. Now, both users and admins can update a user's data and, therefore, I have created a field for each row that logs who last modified the record (modby) and when (modon) so that, if there are any shenanigans, I can ascertain who fiddled last and, in theory, deal with that particular individual without any "he said/she said" nonsense.
Now here is the tricky bit. My users and admins are stored in separate databases on separate servers (the latter being beyond my control) but I have recently discovered the joys of Federated Tables, which work brilliantly. One small quirk, tho; because my users and admins are stored in separate databases and because I want to maximise the number of records I can store in a single database (there is a size limit of 100mb per database), with the company's current rate of expansion and each branch requiring two admin accounts, it is not an improbable scenario that a user and an admin will end up with the same UserID. Therefore, the modby fields store the full username (i.e. UNPREF125 - admins get their own, unique Username Prefix so as to differentiate between admins and users)
Now, perhaps it is because I am such a newbie at Federated Tables but I can't seem to find a way to compare a field in a table on Server A (i.e. modby) with 2 separate fields (i.e. unprefix and userid) in the Federated Table, called from Server B, but I have come up with a workaround by creating an additional field in Server B's table, namely username, which stores the merged values (namely 'DBPREF125') and modby is checked against this instead, which works fine (I'm sure there is an easier way but I will save that lesson for another time).
Now, here is my question. The admin table is currently small (only 26 records) and so I captured the usernames manually, using phpMyAdmin, but I would prefer to avoid having to manually create usernames for the 150+ records in my users table. Is there any way I can get MySQL to pull the values of the userid and unprefix fields, join them together and store the result into the username field of the same record or would I need to turn to PHP for this and, if so, how would I go about this?
I apologise for the length of my question but I hope this will help explain why Google was not my friend today.
Many thanks in advance.
To store the combination in the table:
UPDATE TableB
SET username = CONCAT(unprefix, userid);
Or you can just use it when comparing:
SELECT *
FROM TableA a
JOIN TableB b
ON a.modby = CONCAT(b.unprefix, b.userid);

Besy way to store data about data that is already stored in a database?

I am working on creating a favorites section on my website where users can simply store certain items in their favorites section for easy access. Each of the items are already well-defined and have multiple attributes. So my question is lets say I had 10,000 users and I would like to implement a 'favorites' system, what would be the best way to keep track of what favorite items have been added by each user?
I was thinking implementing this the following way: link each favorited item id to a username and then run a query for if the user with a particular username is logged in than retrieve all the favorited items by that username.
I appreciate any help with figuring out of a good way to do this. My goal is to store in a way that is later easy to retrieve and use the data and minimize redundant information.
It's pretty easy, you need to create a new table with 3 fields:
id
favoriteID
userID
Every time a user adds a new favourite, it adds a new record to this table, storing both the ID of the favorite, and the ID of the user. There is no redundant information and it's easy to retrieve the details of either the favorite or the user by implementing a join query. This is what relational databases are for.
Within an RDBMS you would probably have a many to many table with the user id and article id. You do not need an independent id column:
create table favourites (user_id int, article_id int);
These of course reference your user table and articles table. (Or whatever you have in place of articles.)
You would then need to retrieve all rows for a single user when wanting to show that user's favourites. You might also want to make a combined UNIQUE index on the columns to prevent duplicates.
You may have faster response with something like cassandra where you can simply retrieve based on the key of the user_id and get all their favourites in one easy spot. But then you're dealing with mutilple systems.
I've heard, but haven't had a chance to look into, that MySQL can now support a Key-Value system similar to Cassandra and that may be your best bet.

Imported Contacts

I need a table where to keep imported contacts (emails) by users, something like an address book.
Now the table look like this: imported_contacts: id, user_id, email, etc....
I'm thinking to create a table imported_contacts: id, email, etc and another table user_contacts: id, user_id, imported_contact_id, date, etc to avoid keeping duplicate emails in table imported_contacts. So with the new idea I keep in imported_contacts all imported email in the other table user_contacts I keep relationship between users and imported_contacts.
Is this a useful idea?
If I understand this correctly, if two users add the same contact, it is stored on just one row in the table, and both the users see the same row.
I see two problems with this:
if one user updates the email (or any other information of the contact), the information will also appear updated to the second user, and the initial information of the second user would be lost.
I don't know if you store other fields besides email, but if you do, you must consider that they might have different values, depending on the user; for example, if you store the name of the contact, the first user might write the contact's full name, and the second user, the high-school nickname.
Now it really depends on what this application is used for. If it's just for the internal use of one company, their client database for example, then it might be useful to have any changes propagate to all the users, so problem no. 1 would not really be a problem. But otherwise it wouldn't be ok.

Categories