Is it better to have two separate user tables or one? - php

My web app is going to have two types of users that are 100% different - in fields, functions, and purpose on the site. The purpose of one type of user is to post blogs, and the purpose of the other is to read them and "follow" the posters.
The ONLY stuff they have in common are the need for an id, email, password and a couple other bits of meta data such as date joined, etc.
Should I attempt to stem them from the same account table, or make one table for each?
NOTES
-One potential thing to think about is that, to prevent user confusion, I think emails between the two types of accounts should be unique.
-Readers and Authors will have different sets of data that will need to be stored about them aside from the normal "account" meta data.

I would separate them.
TABLE User {
id
email
password
salt
created
modified
}
TABLE follower {
user_id
...
}
TABLE author {
user_id
...
}
Over time your application will grow. Perhaps now you have two destinct roles - but it may change in the future. You may have authors that also follow other authors, or followers that are "upgraded" to authors. You might also start adding other "roles" and want something like this:
TABLE user_role {
user_id
role_id
}
TABLE role {
id
name
}

Define "user". If a user is somebody who has registered him or herself on your site, using an e-mail address, password and nickname, and who can log on, then stick everyone in the users table.
The things users can or can not do on a site does not differ for a user. It's their permissions that are different. Map permissions to users in a separate table. Don't create a table for each type of user.
Otherwise, when you're adding a new kind of permission in the future, you don't have to add a new table for that type of user (and alter all (sql) code that handles with users: logging in, resetting passwords, and so on). You just add a new type of permission, and map that to their respective users.

it will save you allot of work to just have one table and have a single column in the table that defines which type they are .

No, make one table for each. It will be easier to manage, it'll be scalable

Related

How to handle different types of users when loggin in?

In an application I've been building, I have a users table. The users represent a firm's staff. I also implemented a role/permission system. Permissions are assigned to roles (staff, manager, director, etc.), and roles are assigned to users. Permissions prohibit the use of certain actions in the app.
Now, I'm introducing another user type: customer (will also be able to log into the app). The customer fields are different from the user fields, so I can't store the customer information in users table (and create a role for customers).
(Normally, just creating a customer role for the customers and store the custumers in the users table would be fine, but since the fields are different, I don't think that's an option.)
First, I thought about creating a seperate table for the customers, but I'm not sure if that's okay, because when someone tries to log into the app, I have to check two tables (users and customers) for the log-in credentials. What if I introduce a third user type? Check three tables? That doesn't seem practical/efficient.
So I thought about seperating the log-in credentials from users, and ended up with three tables:
users will hold log-in credentials
staff will hold staff meta/profile information
customers will hold customer information (same as staff)
This way, I can introduce many different types of users. And if I know what I'm looking for, I can get the record. For example, say I want to get/query a staff, I can just do:
SELECT * FROM staff
JOIN users USING (user_id);
The problem is how do I query users when I don't know what I'm looking for? I mean, the logged user can be a staff, customer, etc. I need to do something like this:
SELECT * FROM users
JOIN [specific_table_name] USING (user_id);
How do I know which type of user just logged in? I could store the user type (the target table name?) in users, but will it help in a (single) query? I mean, find the user in users (using credentials), and then join the user information from another table (staff, customers, etc.)?
Currently, I'm thinking about doing two queries. First is to get the user (credential) record, and the second is to get user (say, profile) information (using a field type from user record).
Of course I'll be doing this in PHP. For example (not real code):
$email = "someone#example.com";
$user = get_user($email); // SELECT * FROM users WHERE email = "someone#example.com"
switch ($user["type"]) {
case "staff":
$user = get_staff($email); // SELECT * FROM staff JOIN users USING (user_id) WHERE email = "someone#example.com"
break;
case "customer":
$user = get_customer($email);
break;
// ...
}
// how it's done doesn't really matter. the thing is "type" needs to be checked to get the corresponding user info
Is this best way to handle this? Is there a way to make the queries in SQL (without resorting to PHP)? Like JOIN after WHERE? Or make two queries in one (save the first query result, and use a column value from the first result as a table name in the second query)?
Mentioned tables:
I'm still researching, and I found out that what I'm doing with the tables is called (?) "Class Table Inheritance". It seems clever for non-login related entities (when going from child to parent; e.g. staff -> user), but in reverse (parent to child, e.g. user -> staff|customer|etc.), it seems problematic. Since I figure these things as I go, I'm stuck at the moment.
One solution that just (while typing) occured to me is to use different log-in forms/pages specific to user types. The form/page could let me know the user type beforehand, but I rather not use this method. So, single log-in form for all users.
I'm calling users as the base/parent table, and the stuff, customers, etc. as the child tables, because first insert happens at users, and child tables use user_id from users.
You could create a union and use an alias in the query to define different fields mapping for the same name, if there is no field in one table you just cast the alias for an empty field:
SELECT (staff.name) as name FROM users
left JOIN staff USING (user_id)
UNION
SELECT (customers.first_name) as name FROM users
left JOIN customers USING (user_id);
If the userId is a PK/FK it will be only returned by one table.
I would set all users login info and email to the parent table (customers and staff) and two tables with foreign id key for other data, with users.type as you suggested. It could be done with one query, too and Switch condition is not needed:
SELECT users.email,users.type,staff.field2,customers.field3 from users
LEFT JOIN staff ON(users.type='staff' and users.id=staff.uid)
LEFT JOIN customers ON(users.type='customers' AND users.id=customers.uid);

How better to create Users table?

I created Users table.
After the user registered, The system enter his address, phone, city and more personal details to Users table.
There is another table, called Contacts, there the user add another people details.
Now, if there is Contacts table, How better to save the personal details of the user in Users table? in one json column that contains all the user personal details, or in normal columns (address, phone, city)?
I just do not want to happen a situation of multiple data.
I think separate columns for each field will be the better option!
Well, it would of course be easy to just store it as JSON, but that way, it could be a bit messy to search for certain stuff in the database (say you wish to check all users from a given city for example).
When it comes to user information, I always find the best way to do this is to store only login vital data and the base info in a users table.
Something like:
id | email | password
And then have different tables for the other data.
Name and such (which a user only has one of (of course one could have multiple names, but I usually only store first and last names)) could be stored in a user_information table, which is in a one to one relation with the user (foreign key for the user_id so that it can be quickly fetched when needed).
When it comes to address and phone number, a user could actually have multiple.
I understand that its possible that your system/app is only supposed to support one address or one phone number and the like, but its always nice to make it "right" from the start, so that its easy to just let the user add multiple of them whenever the need is there.
That way, you would have a few different tables:
users
user_information
addresses
phone_numbers
and so on...
The user_information, addresses and phone_numbers would preferably all have a user_id column which would be used for a foreign key to point at the user who owns it. And if you wish to make it possible to use the same tables for contacts, a contact_id could be added too (and a foreign key to point to the contact).

Database Setup for Multilevel User Rights

I'm looking to create a database for users with multi-level user rights and I don't know how to go about doing this. What I mean is that I want a manager of a business to be able to purchase my product; that person would be given Owner rights, but would also be able to grand additional users under that license--those people would be given Manager or User rights. Each level (as well as my level: Admin, and my staff: SuperUser) would obviously have individual rights/privileges).
What I'm asking, more specifically, is how to set up the database. For example, if my business is a corporate calendar/organizer, the Owner would set up departments, each with a Manager and many Users. What's the best and most efficient way to structure the database? Like, would each user (and each calendar entry) have to be associated with an ID that belongs to that specific Owner account? I'm just a little lost as to what the best way to organize the database to keep everything together, as I will have multiple different Owners with their own company structure under them.
I want to use MySQL and PHP.
I tried to make this as logical as possible. I think I'm making it too hard, but I am sure there is a standard that makes it easier....Thanks in advance.
At the very least every product/object whatsoever needs a foreign_key in its table, as for example the user's id. This is necessary and sets the relation from the product/object with the user.
And then it depends on how complex you want your system to become. An easy way would be to just use boolean columns in the user table, like an admin, an editor column and so on, with only true and false as values. In your code you could then use if and case to check if a user is an admin and show him parts of your app or not. Like a delete link for example. But you could also restrict updating and deleting to people whose user has a true value in the sufficient column.
The more complex route would include other id-fields in the tables which set a relation of something to something else. Like say you want the user to be a seller or a buyer, then you would add seller_id and buyer_id columns to the products table and check if the ids correspond with the user_id. But not "the" user_id, but a different user_id which you saved when the user created the product listing for example. This way you could guarantee, that besides your staff the user who created this thing has rights to edit it, too, because of the product's user_id being the same as his user_id (current user) when he is logged in to your system.
You could do even more complex relations but then you'd have to create another table and save other ids in it which relate certain users with say other users. In this table you save let's say a maintainer_id and a maintained_id, both have values of certain user_ids but this way you could make a relation between objects one user could change, though they belong to others. Or if you're talking of customers so the mainter_id would be allowed to write messages to those people with maintained_id, like if someone is a seller and the others are potential buyers.
I'm having a little trouble understanding exactly what you're looking for. From what I've gathered, it seems you want a database that holds permissions, users, and departments. In this very basic example I've created 3 tables. (assuming one user can only belong to one department)
You could set a foreign key in the users table which links to the primary key in the permissions table. The departments table would have the foreign key of the user_id.
You could base all of the logic on what each permission can do with your queries and application side logic.
(I can't embed images due to not having 'enough rep')

Mysql design. Two types of users, two different profiles

I want to design a DB which will be connected to PHP Application. In the app there are two types of users: company and person. Some functionality like adding articles will be done by both so in other tables there are author_id columns. So firstly I decided to create user column.
That's easy: id, username, password, role, active, created where role defines whether user is person or company.
Now I want to add profile table or profile tables depends on what you'd suggest (joined with the previous table by adding profile_id column there).
Both roles have different fields, which are required during registration.
The easiest thing would be to create one table with all required fields for both roles, allow them NULL values and in the PHP app (made in Yii Framework in this case) define requirements for each role in models.
The nicest thing would be to create separate tables for both roles BUT the questions is how to connect these two tables to one table using Foreign Key? Is it even possible. I know I may omit foreign key creation then based on role choose table, and from that table choose profile_id.
Or maybe you have another solution to my problem.
Thanks in advance for replies.
Adrian
You need an intermediary between the page and the database to assign the user to a group that has specific privileges. It's usually accomplished with a user-group-role design.
You can have a table for users system info (username , pass ...), and another for users profile (firstname , birthday ...), and another for groups(superuser , ...).
where user table can have multiple groups: user:one->group:many
user can have one profile user:one->profile:one
I think this is a decent solution.

User's custom profile fields

I am currently working on a system that would allow users to add additional custom fields for the contacts that they add.
I wondered what is the best and most efficient approach to add such ability?
Right now what I was thinking was to have 1 table per users (with foreign keys to a "main" contacts table) and then adding a column for each custom fields that the user adds (since I don't expect to have more then 100-200 users per database shards [sharding is easy since every users never see each-other's content in this system]), although I am not 100% sure that this would be the right solution for such problems.
Maybe you could try to have one separated table to store a reference to the user, plus the field name and value, this way you will be able to have lots of custom fields.
If you go with Boyce-Codd, you separate the information and store them into a table.
Means one table for all users with a foreign key.
One table per user would lead to hundreds or more tables with possible repeated information.
You need to have one table named USERS that stores the id of a user and fixed info you might want. Then, you could have a CONTACT table, that stores the type of contact user might create, and one matching table USER_CONTACT that matches the user unique id with the id of the contact that was created.
With this, you could have advanced data mining on all the information stored, like nowing how many contacts each user created, who created more, etc...

Categories