PHP Link user table to another table - php

Hi I am in the process of making a website that includes a user registration system for my final year of high school major project. The website stores driving logs for learner drivers. I'm kind of confused as to how I should desgin the database. I have a users table which stores the personal information of each user of the site. However, I would like the user to be able to insert information into another table which would be their "logbook" and this to be displayed on the my account page. Do I need to create a table within the database for each user or is there a way of connecting the tables so that i do not have to.

You do not need to create a table for each user. Instead, add a column in your "logbook" table which will contain and refer to the "id" of the user it's tracking. This will likely be the primary key of your "users" table. Then, to get the logs for a specific user, you would query the logbook table for rows only with at specific user ID.
Furthermore, in a more sophisticated setup, you can add constraints to link the two columns. See http://dev.mysql.com/doc/refman/5.6/en/create-table-foreign-keys.html

U will not need table for each user...
Just one table will help u out...
The other table where u want to store user logs should only have reference to user I'd that u have created in users table..
Primary and foreign key - relational table concepts
For eg:
Let ur user has
1.userid
2.first name
3.lastname.... And other colums
Then ur userlogbook wala table should have
1.logid
2.userid
3.other columns...
Hope u got it..

You only need 1 table for the users, each user will be a row inside that table.
As you see in this table below, you need a way to be able to track which logbook record belongs to which user. That's done by storing the users ID (or any unique identifier, usually the primary key) to know exactly which user created the record.
-------------- -----------------
| User Table | | Logbook Table |
------------------------- -----------------------------------
| id | name | ...etc... | | id | user_id | date | ...etc... |
------------------------- -----------------------------------
| |
|_____________________________________|
I don't know how your system works, but I assume you know when a user is logged in right? Probably store their id in a session yeah? Well when you're inserting the logbook record, all you need to do is parse through their user ID in addition:
INSERT INTO logbook (id, user_id, .....) VALUES (NULL, $THE_USER_ID_FROM_SESSION, .....)
The above is pseudo code, you'd need to sanitize the input and actually assign the user id to a variable.
Now for fetching the user-specific information, all you need to do is add a simple WHERE clause:
SELECT id,column_1,column_2,... FROM logbook WHERE `user_id` = $THE_USER_ID_FROM_SESSION
The above is pseudo code, you'd need to sanitize the input and actually assign the user id to a variable.
There are a few questions I have, how much reading/writing are you going to be doing to the table? How are your tables set up?

Related

How to create a relational database with Primary and Foreign keys in Phpmyadmin?

I have installed XAMPP on my Windows Computer, ran the Apache and MySQL modules and browsed to http://localhost and then I clicked on phpmyadmin. I created a database and created a table.
This table was called schools and had a column called ID. I gave this column a primary index. The table also had another column called 'Name' which stored the name of the school.
I then created another table called 'Users' and in this table I made a column called schoolID which I gave an index. The table also had other columns such as first name and last name. I then went to the designer tab of the database in phpmyadmin and clicked create relationship. I then first clicked on the Primary key in the schools table and secondly clicked on the Index schoolID for the users table.
It then told me that the relationship was created successfully however I saw no green line connecting the two keys and when I went to insert into the table 'users'... I was not given a dropdown list of the possible schools that could be connected from school ID's and there was no sign that the two fields were connected. It is as if there is no relationship at all.
If I try to create the relationship again it simply gives me the error 1062 "Internal relationship could not be added - Duplicate entry "testdatabase-testdatabase.users-school' for key 'PRIMARY'"
I then went onto REMOTEMYSQL.COM and created a database following EXACTLY the same steps to find that it worked perfectly. Why is my XAMPP server not creating relationships and what am I doing wrong?
I made a column called schoolID which I gave an index ..
I'm not sure what you mean by that. You want to create a list of schools that a user is assigned to / in a relationship with?
Try setting up your tables as below:
school table
id = auto-increment // <-- your primary key
name = varchar(255)
id | name
----------
1 | Hogwarts
2 | Hard Knocks
users table
id = auto-increment // <-- primary key
name = varchar(255)
school_id = int
id | name | school_id
----------
1 | John Doe | 1
2 | Jane Doe | 1
3 | Foo Bar | 2
Fetch all users going to Hogwarts:
SELECT *
FROM users
WHERE school_id = 1;
Fetch all users going to the school of Hard Knocks!
SELECT *
FROM users
WHERE school_id = 2;
You can alter this, obviously, but hopefully it points you in the right direction. Try and use MySQL from the command line when you're getting started. It'll help you really focus on writing the queries, versus relying on phpmyadmin or anything.
It has nothing to do with XAMPP, rather PMA.
Client is important, but I believe latest PMA must be able to support integrity.
Make sure your tables are created as InnoDB, not MyISAM. Also if you experienced other RDBMS before you may see some surprises. First of all I don't think you can see drop down list in PMA.
Another way to check integrity is to browse table with FK (users in your case). The field with FK must be shown as a link.

Store multiple values in one db column

I am trying to create a pivot table to help keep track of "challenges" in my applications. Basically I have a challenge_task pivot table that creates a relationship between a challenge and a task. When a user that is in a challenge completes a task I want to be able to tell so I can track a user's progress. How is the best way to store multiple users completing a task on a challenge?
I was thinking in the pivot table adding a json column called user_completed to handle this and store the user_id for every user that completes the task for a challenge.
So challenge_task would look like
challenge_id | task_id | user_completed
Is this a good way? Or is there anything that fits this better?
I'd recommend a database structure something like this:
challenge: challenge_id | other data
task: task_id | other data
user: user_id | other data
challenge_task: challenge_task_id | challenge_id | task_id
| possibly more data (such as deadline for completion)
challenge_task_users: challenge_task_id | user_id
| possibly more data (such as status: accepted, in progress, completed)
I dont recommend Json if you want to index your data, because Json can not be indexed.
I think you should make a pivot table between the users and the tasks too, and create the neccesary relations.
I wouldn't recommend you inserting multiple values in one database column.
Note: This is my opinion. Just sharing the way I use it.
A table called tasks_settings which has the task settings.
I find this way flexible because I can always edit the title, description, and reward easily. I can also add 2 more fields here which are valid_till and valid_for. So you can make it expire after a period of time and only for a special rank like staff or all users.
Another table called users_tasks
This one controls the users. Whether they have completed the task or not. This could also achieve what you are looking for.
id | challenge_id | task_id | username | user_completed
I hope this has helped you!

Correct MySQL structure for storing user-based data

So I have a question, I'm hoping it isn't too subjective.
I have a blog-style website, so on the homepage articles are loaded alongside the date published, the user that posted it, etc. Basic data like this.
I store it in MySQL like so:
article_id username date content etc.
1 user1 2015-05-14 01:35:14 my content a
2 user2 2015-05-16 02:33:15 my content b
This way, I can display it using one query, where I retrieve the username, date, content, etc.
My question is. I want to allow users the option to change their username. There are two options I see for this.
Either I continue storing data as I do now, and manually update tables like this with user-related data to the new username. Or I store data by a user_id rather than username, and have an extra query for each article loaded to get the associated username from another user table.
Which is the correct approach?
I ask this because I assume there's a recommended practice for this situation? Is it normal to store data by username and update it, or to store by id to avoid having to do this - but at the cost of the overhead when querying data. I'm guessing it's possible to display the username for id-based data in just one query, but that would still take significantly longer?
Depends. Do you see there is a 1:1 relationship with Article:User if yes, then storing in a single table will probably suffice but generally an user will publish multiple articles which will make it a 1:* relationship and in which case you should create a separate table for UserDetailsd and have user_id as FOREIGN KEY in Article table probably.
You should create a users table, store user_id which would be incremental and a user_name. When showing the user name in your app, join to the users table and show the name from that table and it will always be current. This is the best practice if you wish to allow user name changes. Updating all usernames it the articles table is not recommended. This will also allow you to store other user related information such as email, join date, etc... without having to keep all that in the articles table.
Create a seperate table with all user-related information and alter your current table, so only content and article related stuff is included. That's what I'd suggest you
Make a separate table for users something like:
-------------------
user_id | user_name
-------------------
Where user_id should be PK.
And another table, lets say article should look like:
-----------------------------------------------
arcticle_id | date | content | etc. | user_id
-----------------------------------------------
Where article_id could be a PK and user_id would be the FK from users table, making a relationship which could be used in other tables as well.
You can create a table for users, and use a foreign key on field username, specifying the behavior on updates. Is something like this:
alter table posts add constraint fk_post_user foreign key (username) references users (name) on update cascade;
In this way, when you update a row on table users, all user names on table posts will be updated too.

Register - Login Database Scheme

Here is what I want to ask:
I want to make a system to register patients so then they will be able to login. I have 3 type of users though.
admin (no need for registration)
doctor (standard number of doctors, no need for registration)
patient (they will be registered)
I want to keep more info for them than just id, username, password, email.
I am thinking of having more than 1 tables to do this and link them with primary and foreign keys:
1st table
accounts (it will store the login data)
Example:
acc_id(primary key)
acc_password
acc_username
acc_type
2nd table
doctors_extra_info
Example:
acc_id (foreign key)
doc_info_id (primary key)
doc_name
...
...
3rd table
patients_extra_info
Example:
acc_id (foreign key)
pat_info_id (primary key)
pat_name
...
...
4th table
admin_info
Example:
acc_id (foreign key)
admin_id (primary key)
admin_email
a. Which is the best way of doing this?
b. In the part of
registration, how to deal with primary and foreign keys? Two insert
commands in two different tables? [In order to have the same acc_id
in the account table and the extra info table]
c. At the login part,
I need to check the type of user and redirect (header(Location: ..);)
to a page? Is this the right way of doing it?
Any suggestions?
Thank you.
If you're using PHP then when you insert a record you can instantly retrieve the ID created using mysql_insert_id(). You then use this to create other records as your foreign key.
With regards to redirects, I'd simply get the user type from the database and then check the type of user and redirect to page required.
Generally though the tables you have created do not correlate properly. Remember the defining thing about the people using the system is that they are a person, and shouldn't be deined by their job role. They should have a account_type_id linking to another table. Otherwise you have three tables essentially holding the same information.
For example you should have your tables like this
User table
user_id
first_name
last_name
email
account_type_id*
Accounts type table
user_id
account_type_id*
account_type //e.g. patient, doctor, admin etc
This means now that you can easily extend the database with new tables, user access levels, new columns without having to duplicate the same column across three tables and so on. Try reading up on database normalization. A very good video from youtube is http://www.youtube.com/watch?v=fg7r3DgS3rA

Preserving old data changed by user

I have a users table that has the following fields: userid, phone, and address. Since this is user data, I'm letting the user change them whenever he wants. Problem is I'd like to keep track of those changes and preserve the old data too. Here's some of the ideas I considered:
appending the new data to the old data and using a separator like a pipe. When retrieving the field, I would check for the existence of that separator and if exists, get the chars after it as the new data. (feels cumbersome and doesn't feel right)
setting up a different changes table with the following fields: userid, fieldname, fieldcontent. When/if a user changes data (any data), I would log the event in this separate table under the user's userid, and the name/id of the field and the old content of the field, then I can now overwrite his old data in users with the new. If I want to find all changes made by this user, I would search the changes table by his userid. Problem with this is that I'm mixing all data changes (of all fields) into one table and so the fieldcontent field in changes has to be text to accommodate the varying field types. This still seems better than the first idea, but still not sure if I'm doing the right thing.
What other ideas are there or known best practices to keep old data?
Thanks in advance
Whatever you do don't do the first one.
The changes table is a better approach. It's also called an audit or history table. I wouldn't do a history of key-value pairs however. Instead do a history per relevant table. You can do this in application code or via database triggers. Basically whenever an insert, update or delete happens you record which happened and what data was changed.
Table user:
id
username
email address
phone
address
Table user_history:
id
change_type (I, U or D for insert, update or delete)
user_id (FK user.id)
email address
phone
address
date/time of change
optionally, also store who changed the record
A very simple way that we have used to track such changes is this:
users_history`
userid
changenumber smallint not null
changedate datetime not null
changeaddr varchar(32) not null
phone NULL,
address NULL
primary key on (userid, linenumber)
Each time you INSERT or UPDATE a record in the users table, simply INSERT a new record in the users_history table. changenumber starts at 1 and increments from there. changedate and changeaddr could be used to track when and where.
If a field value has not changed, feel free to put NULL in the respective users_history table field.
At the end of the day, your app does not need to change or store bulky history data in the users table, but you have all if it at your fingertips.
Edit:
This does preserve the old data. See the following example where the user started with a given address and phone, and then 4 days later updated the address, and 5 days later updated the phone. You have everything.
Current users record:
100 | 234-567-8901 | 123 Sesame Street
Sample History Table
100 | 1 | 2009-10-01 12:00 | 123-456-7890 | 555 Johnson Street
100 | 2 | 2009-10-05 13:00 | NULL | 123 Sesame Street
100 | 3 | 2009-10-10 15:00 | 234-567-8901 | NULL
The simplest way to implement this will be have another table just for history purpose, a snapshot. You don't need to mirror all the fields, just
change_id // row id (just for easy management later on if you need to delete specific row, otherwise its not really necessary)
user_id // Original user id
change_time // time of change
data // serialized data before change.

Categories