Im currently creating a role System for a web Project (PHP/SQL)
To start me of I will have ~5 fixed roles which can be assigned to users.
And then I got a lot of different privileges.
Now I have to create a table to assign different privileges to different roles and I wonder whats the best way to do so:
1) Table with columns like that:
id | privilege | sysadmin | editor | ... | guest
0 | db_view | True | False | ... | False
1 | page_edit | True | True | ... | False
...
This seems the best solution as Long as there are only five fixed different roles, but is it still practicable when I open the role system to user defined roles in a future version.
2) Table with columns like that:
id | role | db_view* | page_edit | ... | usermanagement
0 | sysadmin | True | True | ... | True
1 | Editor | False | True | ... | False
...
At the end this table will have a great amount of columns - is that a good idea?
2) Table with columns like that:
id | role | privilege | Value
0 | sysadmin | page_edit | True
1 | Editor | page_edit | True
2 | sysadmin | dbview | True
3 | Editor | dbview | False
...
Here it should probably be enough to just create a dataset for privilges who are true. But it would still require a big table.
Is there another way? What would be the clearest, most flexible way to create that table?
Which way do you learn when you study database design?
Thanks in advance for any suggestions or questions!
This seems like a classic case for a many to many relationship:
TblPrivileges
-------------
Privilege_Id (primary key)
Privilege_name
Other privileges related data
TblRoles
--------
Role_Id (primary key)
Role_Name
Other role related data
TblPrivilegesToRoles
--------------------
PTR_Privilege_Id (reference privilege id in tblPrivileges)
PTR_Role_Id (reference role id in tblRoles)
In table TblPrivilegesToRoles the primary key should be both columns.
Related
First things first. I am totally new on Symfony, and I am trying to solve an issue but I don't know how. So, if my questions seem to weird to you, then please help me by explaining where I am wrong and thank you in advance.
So, in my DB I have the following tables:
payments, with columns: id, merchant_sevice_id, customer_id, status, type, created_at, amount_amount, amount_currency. payment_method_payment_method_type, payment_method_payment_method_id, vat and failed_reason.
and
merchant_services with columns: id, payment_institution_id, account_id, name, capacity, capabilities, created_at, mid, status, and blocked_bins_id.
The two tables are connected with a manyToOne relationship. So, many payments could belong to one Merchant
Now, the problem is when I try to get one Payment and check the relationship with Merchants. The fields of the Merchant are all nulled, while in DB I have values.
So a given record in payments table looks like that:
| id | merchant_service_id | customer_id | status | type | created_at | amount_amount | amount_currency | payment_method_payment_method_type | payment_method_payment_method_id | vat | failed_reason |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 0fede82a-b898-4287-83e3-8f7d28d576db | 548d36d9-f1e6-4854-b513-1559b2499b45 | 237369c4-feed-4e24-964a-638938c7940c | failed | SALE | 2018-06-15 07:36:28 | 100 | GBP | card | f35f78c4-2da7-432a-ace5-c0829db448af | 5 | |
And the related record in merchants is like that:
| id | payment_institution_id | account_id | name | capacity | capabilities | created_at | mid | status | blocked_bins_id |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 548d36d9-f1e6-4854-b513-1559b2499b45 | c7a02b53-6c8b-4aa9-b1af-1c5b4978d844 | 4d239c0f-1fa0-4d70-88b4-95b6f05e7bf5 | Test | 0 | ["AUTH"] | 2018-06-06 06:36:15 | 53 | active | e3d6a222-68cd-468c-a78a-b0da8ff0caf9 |
Then, the output of my query in the DB seems like that:
As you could see, the values of the merchantService are all null (except the ID).
So the question is, what it could make this problem? Could be a serializer? Is that a kind of Symfony issue? Actually I am looking for a hint on where to look for solution of that issue.
Again sorry if my question is too weired, but I am really blocked and I don't know how to continue.
As iainn indicated in his comment Doctrine relationships are by default lazy-loaded (you can change that by using fetch="EAGER" in the ManyToOne annotation). Indeed, you can easily observe that in your screenshot, as the merchantService object has property __isInitialized__ set to false. That means it is a proxy object of MerchantService class.
I'm not sure why I'm struggling with this it seems like a very simple concept. So my struggling makes me think that perhaps my data modeling needs another component...
I'm using Laravel 5 and am trying to define some model relationships. BelongsTo,HasA, etc. Before I can write the code, I need to at least conceptually understand what type of relationship I'm creating.
I have an application to where users can send people referral links, if a person clicks on the link and signs up, their user record makes note of the code that referred them. This way I can trace back and see who referred a particular user. But a referral is NOT necessary to sign up
Tables:
USERS
+----+-------------+
| id | referral_id |
+----+-------------+
| 1 | 1 |
| 2 | null |
| 3 | 2 |
+----+-------------+
REFERRALS
+----+---------------+---------+
| id | referral_code | user_id |
+----+---------------+---------+
| 1 | 12345 | 2 |
| 2 | 54321 | 2 |
| 3 | 99999 | 2 |
+----+---------------+---------+
USERS.REFERRAL_ID references REFERRALS.ID
and
REFERRALS.USER_ID references USERS.ID
But what kind of relationships are these?
The only one that seems obvious to me is that REFERRALS.USER_ID belongs to USERS.
But what about USERS.REFERRAL_ID, saying it belongsTo Referrals doesn't feel right, as that record isn't required and I don't feel like it 'owns' the user by any means. Saying it hasA referral doesn't feel correct either, as again the user doesn't own or even require the referral.
I guess what is confusing me is that REFERRALS is an optional entity.
How should I conceptualize the relationship between USERS.REFERRAL_ID and REFERRALS.ID?
Is it bad to have this sort of "circular reference"? Would I be better off creating a pivot table?
No need to add any reference to the Referrals table in the User table, you already have that relation defined in the referral table ( user_id column )
Further reading: https://en.wikipedia.org/wiki/Database_normalization
The Relationship is
USER has many REFERRALS
REFERRAL belongs to USER ( inviter )
REFERRAL belongs to USER ( invitee )
Modify your REFERRALS table
+----+---------------+---------+------------+
| id | referral_code | user_id | invitee_id |
+----+---------------+---------+------------+
| 1 | 12345 | 2 | 1 |
| 2 | 54321 | 1 | null |
| 3 | 99999 | 3 | 1 |
+----+---------------+---------+------------+
user_id is the id of the user that sends the invitation
invitee_id is the id of the user that accepts and registers
invitee_id column is nullable() and will contain the id of the invitee from users table when they join.
Think of it as a JOIN table between inviter and invitee.
I have created a privilege system for my application which allows/disallows access to specific pages based on user input.
The table looks something like this:
page_id | client_id | sys_group_no | name | friendly_name | viewable |
1 | 4 | 1 | home | Home | true |
2 | 4 | 1 | admin| Admin Home | false |
So if the user in client_id 4 is of group 1 they are NOT allowed to view 'Admin Home' it isn't actually quite this simple but for the sake of this question we can pretend.
The problem is as maintenance goes on this table get out of date quickly, and when you have a few thousand rows, constantly checking the table against the actual page names (using scandir() and array_diff()) will be expensive. Is there a different paradigm for checking this kind of integrity other than direct comparison? - For instance would hashing my $page_array and comparing it be a better approach?
Recently I have been planning a system that allows a user to customize and add to a web interface. The app could be compared to a quiz creating system. The problem I'm having is how to design a schema that will allow for "variable" numbers of additions to be made to the application.
The first option that I looked into was just creating an object for the additions and then serializing it and putting it in its own column. The content wouldn't be edited often so writing would be minimal, reads however would be very often. (caching could be used to cut down)
The other option was using something other than mysql or postgresql such as cassandra. I've never used other databases before but would be interested in learning how to use them if they would improve the design of the system.
Any input on the subject would be appreciated.
Thank you.
*edit 29/3/14
Some information on the data being changed. For my idea above of using a serialized object, you could say that in the table I would store the name of the quiz, the number of points the quiz is worth and then a column called quiz data that would store the serialized object containing the information on the questions. So overall the object could look like this:
Questions(Array):{
[1](Object):Question{
Field-type(int):1
Field-title(string):"Whats your gender?"
Options(Array):{"Female", "Male"}
}
[2](Object):Question{
Field-type(int):2
Field-title(string):"Whats your name?"
}
}
The structure could vary of course but generally i would be storing integers to determin the type of field in the quiz and then a field to hold the label for the field and the options (if there are any) for that field.
In this scenario I would advise looking at MongoDB.
However if you want to work with MySQL you can think about the entity-attribute-value model in your design. The EAV model allows you to design for entries that contain a variable number of attributes.
edit
Following your update on the datatypes you would like to store, you could map your design as follows:
+-------------------------------------+
| QuizQuestions |
+----+---------+----------------------+
| id | type_id | question_txt |
+----+---------+----------------------+
| 1 | 1 | What's your gender? |
| 2 | 2 | What's your name? |
+----+---------+----------------------+
+-----------------------------------+
| QuestionTypes |
+----+--------------+---------------+
| id | attribute_id | description |
+----+--------------+---------------+
| 1 | 1 | Single select |
| 2 | 2 | Free text |
+----+--------------+---------------+
+----------------------------+
| QuestionValues |
+----+--------------+--------+
| id | question_id | value |
+----+--------------+--------+
| 1 | 1 | Male |
| 2 | 1 | Female |
+----+--------------+--------+
+-------------------------------+
| QuestionResponses |
+----+--------------+-----------+
| id | question_id | response |
+----+--------------+-----------+
| 1 | 1 | 1 |
| 2 | 2 | Fred |
+----+--------------+-----------+
This would then allow you to dynamically add various different questions (QuizQuestions), of different types (QuestionTypes), and then restrict them with different options (QuestionValues) and store those responses (QuestionResponses).
I have a scenario and i'm confused about how i can go about designing the database schema for it.
In my software (php)
there are companies and applications.
companies need to have licenses to access applications.
now the fields (for form while purchasing licenses) for each application is different.
for ex:
for application1:
fields are:
no of users
no of groups
for application2:
no of users
for application3:
number of hours of usage
Prices are based on these fields.
Now i need to design schema for this so that on one page company can manage licenses for all applications.
How can i make this schema generic?
Please help.
Thanks.
You can go with this type of structure
select * from applicationMaster
| APPID | APPNAME |
------------------------
| 1 | Application1 |
| 2 | Application2 |
ApplicationMaster will go with main Application related details which won't be repeated such Name, date etc.
Query 2:
select * from applicationField
| FIELDID | APPID | FIELDNAME |
---------------------------------
| 1 | 1 | NoOfUsers |
| 2 | 1 | NoOfGroups |
| 3 | 2 | NoHourusage |
ApplicationField can adjust any number of field for a particular appId.
So AppId 1 has 2 fields NoofUsers and NoOfGroups. It is also capable to adjust newer fields for a particular app if you want.
Query 3:
ApplicationValue will have the values for every license aplication so it will have compId which represents which company has applied using fieldId which refers to applicationField table we can get for which app values are stored.
select * from applicationValue
| ID | COMPID | FIELDID | FIELDVALUE |
--------------------------------------
| 1 | 1 | 1 | 50 |
| 2 | 1 | 2 | 150 |
| 3 | 2 | 3 | 350 |
| 4 | 3 | 1 | 450 |
| 5 | 3 | 2 | 50 |
applicationPriceMaster stores the price package for each application. There could be multiple package for a application.
select * from applicationPriceMaster
| APPPACKAGE | APPID | TOTALPRICE |
-----------------------------------
| 1 | 1 | 50 |
| 2 | 1 | 100 |
For each application package its details will posted in this table.
select * from applicationPriceDetail
| APPPACKAGE | FIELDID | QUANT |
--------------------------------
| 1 | 1 | 1 |
| 1 | 2 | 1 |
| 2 | 1 | 10 |
| 2 | 2 | 1 |
NOTE Please check the structure as it is now too complex and check what type of queries you would be running on these table and its performance.
select apm.APPPACKAGE, TOTALPRICE from
applicationPriceMaster apm
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=1 and QUANT=1)a
on apm.APPPACKAGE = a.APPPACKAGE
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=2 and QUANT=1)b
on
a.APPPACKAGE=b.APPPACKAGE
SQL FIDDLE:
| APPPACKAGE | TOTALPRICE |
---------------------------
| 1 | 50 |
For single filter you have to use this query, so you have to increase number of inner query with the number of inner filter.
select apm.APPPACKAGE, TOTALPRICE from
applicationPriceMaster apm
inner join
(select APPPACKAGE from applicationPriceDetail
where FIELDID=1 and QUANT=1)a
on apm.APPPACKAGE = a.APPPACKAGE
NOTE-This query is quite complex and will only work if the values are same as mentioned in the packagedetail table and will work only if the values are 2 filter you have to remove 1 inner join if there is only 1 filter. So I suggest you to reconsider before using this approach.
What you have there, could be easily mapped to Classes in an OO language (like PHP). You have an Abstract License, and then 3 Subclasses (ApplicationByUsersAndGroups, etc). Then, mapping to a Relational database is a very common problem, here is a nice article about it: http://www.ibm.com/developerworks/library/ws-mapping-to-rdb/
It has 3 options, it depends on the way you want to structure your application which one you should use. I recommend reading it, it is not that long.
One way is
Table LICENCES:
LICENSE_ID ==> UNIQUE IDENTIFIER
COMPANY_ID ==> references table COMPANIES
APPLICATION_ID ==> references table APPLICATIONS
LICENCE_TYPE ==> either of "BY_GROUPS_AND_USERS", "BY_USERS", "BY_HOURS"
LICENCE_BODY_ID ==> ID of specific body table
[...]
Table LIC_TYPE_BY_GROUPS_AND_USERS:
LICENCE_BODY_ID ==> body identifier
NO_GROUP
NO_USERS
[...]
Table LIC_TYPE_BY_USERS:
LICENCE_BODY_ID ==> body identifier
NO_USERS
[...]
This way, your intention is clear. Even after long time comming back, you will know in no time how things are organized, which fields are used in which case...
how about a table structured this way:
LicenseId int PK
CompanyId Int PK
AppId Int PK
LicenseType int
NumberOfUsers int
NumberOfGroups int
NumberOfHours int
Price Money
Depending on LicenseType, you will use different column in your business logic,
you might need to add CompanyID and/or AppID, that depends how you going to structure those tables as well as relation ships between company/app/license.
Some questions to think about:
Can one company have different License Types for same App?
Can one company have different Apps?
Dont complicate things, if the number of users is unlimited then set it to 999999 or some other max value.
This keeps the license check logic (which will run every time a user logs in ) simple and the same for all applications.
You will need extra logic in the licenses maintenance application, but this should also be pretty simple:
if the cost_per_user is = 0 then set no_of_users = 99999
Again you end up with the same licensing screen and logic for all your applications.