I have working website in PHP with a MySQL backend which has several tables for different purposes.
This site is based on different parts or 'environments' like a bugtracker, project management, etc.
There is one central 'users' database which has all the users with the associated details in them.
In each of previously mentioned 'environments', which all have their own set of tables, it is possible to specify a user ID in certain fields.
e.g. the bugtracker table has a column called AssignedTo which contains the user ID's of users to whom bugs have been assigned.
The field type of these 'user ID' columns (like the AssignedTo example) is the same as the UserId field in the central users table, which is an unsigned, zerofilled INT(5) field.
Now I have a request from the users of this site to also allow to specify user groups in certain of these user ID fields.
So again reffering to the AssignedTo example, it should now be possible to also assigned a bug to a user group, instead of a specific user.
What's the best way to do this regarding the PHP scripting and the database layout?
Now I have all these fields set to the same type as the UserId of the central users table, which is INT(5).
However my UserGroupId field in the UserGroups table, is of a different format, INT(3).
I could make this field also into an INT(5) field, but that would not solve the 2nd issue I'm having: how to see whether the AssignedTo value is reffering to a specific user, or to a usergroup.
I was thinking about make the UserGroupId field start from 99999 and counting downwards, while the UserId field is starting from 00001 and counting upwards, thus assuming that if the AssignedTo starts with 9, it's reffering to a usergroup.
But this doesn't seem like a clean solution to me...
Any better ideas?
Thanks!
I think I understand what you are trying to say. I have a question. Can a user be in multiple UserGroups?
I would probably add a column in the bug table that says whether the AssignedTo value refers to a UserID or a UserGroupID.
Create a separate table for UserGroups.
If Users can belong to multiple groups, create an association table like: AssociationID, UserID, UserGroupID.
Otherwise if each user can only belong to one group, just add a UserGroupID column to the Users table
If I am understanding correctly, my solution would be to instead of having an AssignedTo column pointing to either a user or a user group, I would create two columns. One pointing to the user id and another pointing to a user group id.
Actually a colleague at work came up with the following solution which I really like:
Change the UserId and UserGroupId field types from INT(5) to INT(4). And leave the different fields like AssignedTo set to INT(5).
Now in the PHP code I can add a prefix number to either the 'UserId' or 'UserGroupId' value, this prefix number can be used to determine if the value is reffering to a UserId or a UserGroupId value.
So if the AssignedTo field is '10005' it means it's a 'user' with 'id: 0005'. Also to prevent having to update all existing records, values which have a '0' at the first position will be considered users
The advantage over using positive/negative values here is that in both the Users and UserGroups tables I can still use a positive 'Id' field which can be left to autoincrement. As far as I know auto-incrementing is not possible with negative values
Related
I have three tables, and I'm just looking for a way to make this work.
tbl_campaigns has the columns "id" and "campaign". This one is fairly straight forward, it's just campaign names with an ID number that is auto-incremented so they have unique IDs.
tbl_users has an "id" column so each user has a unique ID number, standard stuff.
tbl_permissions creates a new row whenever a new user is created. This means its "id" column has unique ID values that match to the ID of a user in 'tbl_users'. The columns have been named to match the ID value of a campaign each time a new one is created, for example, the column "campaign_1" is relevant to the campaign in 'tbl_campaigns' with the ID of 1. The idea is this table data is filled with either 1's or 0's.
If a row with the ID of 1 has the number 1 for the column "campaign_1", then the user with the ID of 1 is approved for the campaign with the ID of 1 in the campaign table. If it were 0 then they're not approved for it. The same logic applies for columns "campaign_2", "campaign_3" etc..
Anyways, the issue I'm having is displaying this information on a front-end, as I only want the user to be able to see the campaigns they are approved to run in a drop-down list. When the user is logged in it stores their User ID in a session, I'm not sure if there's a way around it with this method.
Is there any way to get around this? Please note I've done this in procedural PHP as I'm still in my early days, so if anyone has a solution along these lines it would be much appreciated. Sorry if it's a little confusing. I am aware it's a bit ham-fisted, but I just want it to work first.
I believe that your schema needs to be improved, as the table structure should not have to change every time that you add a new campaign.
keep tables tbl_campaigns and tbl_users as they are
create table tbl_permissions with 4 fields (id, user_id, campaign_id and permission)
To check if a user has permission use a query like this:
SELECT permission FROM tbl_permissions WHERE user_id = ? AND campaign_id = ?
So, every time you create a campaign add a corresponding record to the tbl_permissions table. No need to add a new column.
I think the best practice to do this is as follows:
- Create HTML to show to the user(if you don't have it, let me know so i can work on one you can use)
- Create JS archive that will be in charge of calling PHP file and show the result in your HTML(if you don't know how to make it let me know so i can help you)
- Create PHP file, this is going to be in charge of consulting your data base and give the result disired for your select (if you don't know how to make it, let me know)
It is pretty easy to make this work, let me know if you need more help.
I want to create a MySQL database for a project in which users can come and make comments on other profile. Every profile has a unique id to identify it, now when a user comes and makes comment on other profile I'll need to store the user id of the person who made the comment and the person on whose profile the comment was made, along with that I'll need to store the comment in the database.
As many users can make comments on a single profile, I'll need to store all the comments and the users who made them on a single profile. For this how many tables should I create and how many columns should they have? For this I'm thinking about creating a table for named user_comments and that has column user_id, commenter_id (all the commenter who commented their id separated by comma), comments (then all the user comments separated by comma).
Will this work?
For this I'm thinking about creating a table for named user_comments
and that has column user_id ,commenter_id(all the commenter who
commented their id seprated by comma) ,comments(then All the user
comments seprated by comma)
God no! You are almost there:
Table comments
id INT AUTO_INCREMENT
recipient_id
sender_id
message TEXT
[ sent DATETIME ]
[ other meta data ]
Store one message in message. Create one row per message. Never store several records in the same field separated by anything.
I'd have a profile_comment table:
id, text, profile_user_id, commenter_user_id, created_at
And a user table:
id, name, email
You can see here that the first table has two foreign keys to the user table - one points to the owner of the profile, and the other points to the owner of the comment. You can sort them in order of created_at to list them as you would on a blog, either in forward or reverse order.
Now, when you are rendering a profile page, you can get the profile id from your query string:
$profileId = isset( $_GET['profile_id'] ) ? $_GET['profile_id'] : null;
From there, you can add it into a SQL query:
SELECT * FROM profile_comment
WHERE profile_user_id = :profile_id
ORDER BY created_at
The colon mark here is a placeholder you can use with a parameterised query, which helps protect against SQL injection. However, you can build the statement as a string if you are careful to untaint any user input you insert into it.
I have a database with employees. the columns are first name, last name, department, internal number etc..
As for today it is a database only for one organization but in future i want to add to this database employees from other relative organizations.
What is the right way to do it:
To add another field to the first table ?
To create another table with 3 fields: id, organization_name, employees ( where in this filed i would put comma separated values of id from first table) ?
if the second answer will be chosen what will happened when an update query will be executed simultaneously from different accounts to the same organization. For example: i will be adding a user with id 55 to organization 'Police' and at the same time another administrator will be adding to the same organization a user with id 65..
In this case is there a possibility of error or data-loss ???
If someone had this kind of problem before, i really would like to read about it..
Thank You..
If the organization is only a number to group the users, then I would suggest to put them into the employees table. However if you have more information about the organization (e.g. name, address .. ) then make a new table for the organization and save the primary key of the corresponding organization in the employees-table.
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...
I already have a simple registration system in place using php and mysql. It operates well enough. However, when people visit my site and register, I would like for them to register as part of a particular group. So, I was thinking that registration would happen like this:
Visitor lands on index.php, clicks on "Group Registration" link.
Visitor supplies group name and group password. [A new table is created for that group where all user data will be stored for that particular group]
Visitor then is prompted for typical registration data--name, email, etc.--and that data is stored in the newly created group table.
Any subsequent visitors associated with that group would click on "User Reg"
The visitor would be prompted for group name and password
If correct, then he would be prompted for typical reg data, to be stored in his group's table.
What I don't know how to do is implement the group authentication prior to allowing user registration. Can someone help me with that?
If the visitor is entering a group name and password, then you can authenticate the same way you are doing the users. You just need to first ask yourself if the group name needs to be unique or the group/password combination.
As for your idea to add a new table for each group, that is a bad idea. Imagine if you have 100 groups. Then you will have 100 tables just for groups. If you get up to 1000 groups, then you will have 1000 tables. Try managing that. It will get really frustrating really fast. Instead, what you should do is to first create a "Group" table with all the associated data (group name, password, etc). Then add a field to your User table that will hold the associated id from the Group table. That way, whenever you look up the user, you can easily check what group the user is in simply by joining the two tables rather than trying to figure out what table to look at as in your original plan.
What you want to end up with is a table for your users and another (single) table for your group information. The user table will have a foreign key field to link it to a group. When a user joins a group, you will enter a value in that field. Users not in groups will have a null value in that field. If users can create groups, they will simply be adding a new row to the groups table.
If your users can be in multiple groups, set up your tables like this.
USER
- id
- username
- password
- etc...
GROUP
- id
- name
- password (?)
- etc...
USER_GROUP_CR
- fk_user
- fk_group
The USER_GROUP_CR table is a "cross reference" or "link" table that will allow you to create a many to many relationship. This way you can have users in multiple groups without creating extra tables. When a user joins a group, add a row to the USER_GROUP_CR table with the id of the user and the id of the group. You can query this table to find out which groups a user belongs to, or to find out which users are in a group.
You should not create a new table for every group.