Create a lookup table with Doctrine2 - php

I have recently installed Doctrine2 on my web server and all works great. I have setup all my entities but now I'm at the point where I want to create a lookup table and I'm a bit confused how to do that. I want a table which looks like this:
tbl_Role tbl_User
+--------+----------+ +--------+----------+--------------+----------+
| id | Name | | id | Name | Password | Role |
+--------+----------+ +--------+----------+--------------+----------+
| 1 | Admin |
| 2 | User |
| 3 | Free |
+--------+----------+
Between the Role and the User table consists a OneToMany relation (one Role has many Users) and this table does not change in future. I do not want to use Enums because of the update or reorder problem with them (if nevertheless something changed)
My question now is how I can represent this lookup table as a Doctrine entity? Normally if I want to create a new User I have to get the fitting Role from the DB and set it as a reference in the User entity. This seems a bit expensive to me. It would be great if I could have only the Role IDs in static PHP fields so I can set them as reference for the User. Is this possible?
Another problem is how I get the lookup values into the database. Can I implement a method into the Role entity itself which is executed after the Role table is created? This way it would be possible to mark the constructor as private and all values are present after a migration.

First of all, it won't be too expensive, because Doctrine2 has a few cache layers and these queries will be efficiently cached since the Role table won't change.
Anyway, if Role table won't change, I'm not sure if it should be kept in database. You could create a "static" factory service for it to create simple value objects as a part of your domain layer.

Related

Best way to create relational database model for different Customer modals in Laravel

In my Laravel project i have 3 kind of types, Vehicle Owner, Driver and Customer models.
When I'm adding credits and debts for all kind. It's working but I'm not happy with solution
Because:
There are several common fields repeates.
When user will add credit/invoice which joins with 3 tables.
Financial table seems more complex
Finance
userType | userID | amouth
------ | ------ |-----------
VehicleOwner | 5 | -500
Driver | 5 | 200
Customer | 5 | 200
Maybe there is a solution could be relate all 3 tables with one table:
In my case i have many related info between these type and would like to use in common instead of joining the data in each table.
1.Driver (extend driving license info)
2.Customer (extend corporate info)
3.Vehicle Owner (extend driver info)
I'm new in Laravel and looking for best practice? I'm waiting for only laravel code practices.
You can have a user_type field (tinyint (1)) in users table.
All kind of users will be in this table.
Customer will have user type of 1, drivers 2 and vehicle owners 3 etc.
You can store amount in User model and add field user_id in Driver, Customer and Vihacle owner models.

How do I design a flexible MySQL notification schema that references multiple tables?

I decided to work on a notification system with inspiration from another StackOverflow post that suggested I break up the notification from the body of the notification. As such, I have the following schema:
notifications
id | user_id | notification_object_id | is_read
notification_objects
id | message | type
I have it set up this way so I can create a notification object and send this out to multiple users in the case the notification object applies to multiple people. The type is there to condense messages into one notification by type, sort of the way Facebook says, "John Doe, John Smith, and 27 other users commented..." rather than giving you 29 separate notifications.
(The naming schema of the table and column are for CakePHP 3's 'contains')
What I need help on is a way to tie in the different users or objects that would be playing a role in the requests. A user might have commented, so I'll probably need the user_id of the user who messaged and need to store that somewhere.
There are other cases besides users; one might want to know the id of the comment such that he can click the notification and go straight to comment/81. I have many use cases where I want to store the different types of ids that are foreign keys to other tables (users, comments, articles, etc.), some of which might need two foreign keys (say you want to mention "Chris has commented on your article 'How to beg StackOverflow for help'") and have the user_id for Chris and the article id for the article both linked in the notification.
Each different type of notification could have different values and tables it needs to pull information from. What's a good place to start on creating this schema?
I'm going to try and answer this question from an OO perspective. When speaking in classes, not in tables, you'd probably start with something like an AbstractNotificationObject class with the basic properties (date, time, maybe a message) and several specialization classes like NewCommentNotificationObject with additional properties (comment, commenting user) or a NewFriendNotificationObject. Going down to the database schema, you could then apply one of the typical ORM patterns.
Concrete table inheritance (just for completeness)
Using concrete table inhericance would probably not be a good idea, because it would boil down to a separate table for each notification type (i.e. a comment_notification_objects table and maybe many more). This would not scale well, and you would not be able to reference them from the notification table using a foreign key. Also, you would not be able to select a set of notifications of different types with a single query (without something like a UNION).
Single table inheritance
Single table inheritance would use only a single table with a type discriminator column. This single table (let's call it notification_objects) would need to contain a type column that describes of what type of notification the record actually is (you actually already have that in your schema). You'll also need columns for all properties that special notification types may have (for instance, a user_id and a comment_id column).
+--------------+
| notification |
+--------------+
| id |
+--| object_id |
| +--------------+
|
| +-----------------------+
| | notification_objects |
| +-----------------------+
+->| id PK |
| date |
| type |
| user_id FK |--...
| comment_id FK |--...
| friend_id FK |--...
| [more fields to come] |
+-----------------------+
Pros:
Load all notifications with a single query
Keep referential integrity with foreign keys
Cons:
Scales badly (you'll need to add new columns for each notification type)
Table will be sparsely populated (many columns will be NULL)
I would recommend this schema when you have a set of notification types of moderate size that does not regularly change.
Class table inheritance
Class table inheritance is somewhere in between; here you would create a central notification_objects table and separate tables for each notification type (for example an additional comment_notification_object table with an id column (which in turn is a foreign key to the notification_object table and a user_id and column_id:
+--------------+
| notification |
+--------------+
| id |
+--| object_id |
| +--------------+
|
| +----------------------+ +------------------------------+
| | notification_objects | | comment_notification_objects |
| +----------------------+ +------------------------------+
+->| id PK |<--+--| id PK/FK |
| date | | | comment_id FK |--...
| type | | | user_id FK |--...
+----------------------+ | +------------------------------+
|
| +--------------------------------+
| | newfriend_notification_objects |
| +--------------------------------+
+--| id PK/FK |
| friend_id FK |--...
+--------------------------------+
[more TABLES to come...]
Class table inheritance would also allow you to query all notifications with a single select query. Depending on how much of the data you need, you'll need to add JOINs to the respective specialized tables.
Pros:
Scales well/Add new types without modifying existing structure
Keep referential integrity with foreign keys
Cons:
When you need more than the minimal set of fields, you'll need to JOIN the specialized tables (possible performance impact)
I would recommend this schema when you have a lot of different notification types or extend your object model often and need to change/add new notification types on a regular basis.
Outside the relational box
Your question asked explicitly about relational schema, so I've focused on that. When thinking outside this box, alternate solutions might include:
Schemaless NoSQL databases
Messaging systems that follow a publish/subscribe architecture

Multi-Table User Authentication

I am currently developing a Student Information System that is going to be used by educational group to provide students & teachers a portal.
I am using Laravel4 which has a good authentication driver built in but can use only one table for authentication. I am unable to figure out how to authenticate them because I have users in multiple tables. Example :
SchoolOne_students
SchoolOne_teachers
SchoolTwo_students
SchoolTwo_teachers
and so on....
A significantly better way, rather than multiple users tables, would be to link each user to their school and status (teacher or student). You certainly can twist Laravel into doing what you want, but in order to prevent conflicts between the four different user types, you'll probably end up having to rewrite a large part of the entire authentication package.
What I would do is, in your users table, have an ENUM column, with the options student and teacher. Then, have an integer column, school_id (with a separate table for school data, if needed). This will allow much more flexibility, and when your design requirements change (yes, they will change), you'll be able to take them in stride.
Using this method, you should not have to modify any of Laravel's own code.
if all the tables have identical schemas, you could create a view that does a UNION of all the tables and then use that view as your Laravel auth table. I am not saying this is an ideal solution, but if you have restrictions on altering the existing tables and must use them as is, this could work.
The view would not be update-able (I don't believe so, at least) so adding or updating users would require specific add/update code, but for Auth, this may do the trick.
CREATE VIEW users_combined_view
AS
SELECT id, username, password
FROM schoolOne_students
UNION
SELECT id, username, password
FROM schoolOne_teachers
UNION
...
note - this method would be somewhat useless (ok, totally useless) if username was not unique across the tables
A good database design is scalable.
This is particularly a bad idea:
SchoolOne_students
SchoolOne_teachers
SchoolTwo_students
SchoolTwo_teachers and so on...
There should be only one table for all the users, in your case for students.
There should be another table for Schools where all the school information will be stored.
Then you should join the students table with schools table by adding a school_id field to the schools table where the school_id will be stored for the corresponding students row.
===Students Table===
+-----------------------------------------
+ id | name |school_id | ... | ... |
+----+--------+----------+-----------+----
+ 1 |Student1| 5 | ... | ... |
+----+--------+----------+-----------+----
+ 2 |Student1| 3 | ... | ... |
===Schools Table===
+-----------------------------------------
+ id | name | ... | ... | ... |
+----+--------+----------+-----------+----
+ 3 |School 3| ... | ... | ... |
+----+--------+----------+-----------+----
+ 5 |School 5| ... | ... | ... |
+----+--------+----------+-----------+----
This way you can add as many schools as you may want and students for them
I hope this will help

FOSUserBundle or PUGXMultiUserBundle to have two different user profiles (Symfony2)

I'm doubtful about how to approach this problem:
My Symfony2 app for this issue has two different profiles, name 'em "Seller" and "Buyer". The goal is to keep a bunch of attributes about a "Seller", and, on the other hand, not much about the "Buyer" (email and password would do it).
I realise that it's not easy to have two different entities log in and register using FOSUserBundle. There are quite some other bundles, such as PUGXMultiUserBundle that 'hack' FOSUserBundle, and are not easy to config/implement.
So my quiestion is: Is it more correct to use the hack PUGXMultiUserBundle proposes, dealing with its implementation and config, or is it better to stick to FOSUserBundle, have a User entity, and a one-to-one relation with a "Seller" entity that represents the attributes of a Seller different from a buyer? There would be another problem with that approach, with the registration form, that should be splitted in two, for Seller and Buyer register (which I don't know if it is possible/advisable using FOSUserBundle)
I hope you guys help me get it right. Cheers :)
I would definitely use the PUGXMultiUserBundle for that. I don't think it's a hack, it just implements a discrimination table that will be like:
1User Table
----------------------------------------
| id | username | type |------------
|-----|-----------|--------|------------
| 1 | mgdepoo | buyer |------------
| 2 | Sydney_o9 | seller |------------
----------------------------------------
2Buyer Table
----------------------------------------
| id | buyer_specific_field_1
|-----|---------------------------------
| 1 |
----------------------------------------
3Seller Table
----------------------------------------
| id | seller_specific_field_1
|-----|---------------------------------
| 2 |
----------------------------------------
That's all there is really.
I think that's exactly what you need especially if you wish to have different profiles for your users. You will have 2 registration forms as well (but you can make one with a choice box buyer/seller if you want to).
I personally use this bundle and it works great for me. Now, one of the question you might want to ask yourself is what if a buyer wants to be a seller as well. Does he want to have another email address? That is a choice that you'll have to make.

Storing application permissions in a database

I'm developing an application for our company that eventually will have lots of ways of restricting users to particular sections/modules. While the application is still small, I'd like to move to a new method of storing permissions that, as the application grows, will remain easy to maintain and query.
Currently in our MySQL database we have a table called "user" which stores the user's ID, username and password. In a separate table called "user_acl" is the following:
user_acl_id
acl_root
acl_news_read
acl_news_write
acl_news_modify
acl_reports_read
acl_reports_write
acl_reports_modify
acl_users_read
acl_users_write
acl_users_modify
We only have 3 modules at the minute, but over time more will be created and permissions for each will need to be added.
Rather than create a column for each permission, is there any other way or storing this information?
I would do it this way.
table name: permission
columns: id, permission_name
and then I can assign multiple permissions to the user using a many to many relationship table
table name: user_permission
columns: permission_id, user_id
This design will allow me to add as many permission as I want, and assign it to as many user as i want.
While the above design go with your requirement, I have my own method of implementing ACL in my application. I am posting it here.
My method of implementation of ACL goes like this:
User will be assigned a role (Admin, guest, staff, public)
A role will have one or many permissions assigned to them (user_write, user_modify, report_read) etc.
Permission for the User will be inherited from the role to which he/she is
User can be assigned with manual permission apart from the permission inherited from role.
To do this I have come up with the following database design.
role
I store the role name here
+----------+
| Field |
+----------+
| id |
| role_name |
+----------+
permission:
I store the permission name and key here
Permission name is for displaying to user.
Permission key is for determining the permission.
+----------------+
| Field |
+----------------+
| id |
| permission_name |
| permission_key |
+----------------+
role_permission
I assign permission to role here
+---------------+
| Field |
+---------------+
| id |
| role_id |
| permission_id |
+---------------+
user_role
I assign role to the user here
+---------------+
| Field |
+---------------+
| id |
| user_id |
| role_id |
+---------------+
user_permission
I store the manual permission I may allow for the user here
+---------------+
| Field |
+---------------+
| id |
| user_id |
| permission_id |
+---------------+
This gives me more control over the ACL. I can allow superadmins to assign permission by themselves, and so on. As I said this is just to give you the idea.
Like Ibrahim says, create a new table specifically for your permissions. Assign a numerical value to a user which represents their permission level, say 1 = read, 2= write/read, 3 = modify/write/read. Then in your code, check for proper permission level before allowing a user to perform a specific task. If they don't have the required value (3 to modify or >=2 to write) then you block that ability.
In a very famous MySQL performance book High Performance MySQL, the author specifically mentioned ACL as where data type like SET could be used. They use following example to demonstrate such use cases:
CREATE TABLE acl (
permissions SET('CAN_READ', 'CAN_WRITE', 'CAN_DELETE') NOT NULL
);
INSERT INTO acl VALUES ('CAN_READ,CAN_WRITE');
SELECT permissions FROM acl WHERE find_in_set('CAN_READ', permissions);
The problem is that, mentioned in the book as well, you can't modify the permissions set easily (you have to use ALTER TABLE), neither can you declare a column typed SET as an index, which may causes performance issue.
You can also use something like TINYINT to "wrap" the ACL list, the cons is that it's harder to read as well as to code SELECT sentence.
I think you should have five tables:
user
user_x_profile
profile
profile_x_function
function
You set up various "generic" profiles "viewer", "employee", "manager" etc.
You set up a "function" entry for each object you want to control.
Then link the functions to the profiles in profile_x_function.
Then assign one or more profiles to each user.
This cuts the administration effort. Say you want to add another function that only "managers" can use -- you just add a new entry in the function table then add an entry in the "profile_x_function" table which links to the "manager" profile the permission to the manager profile and its available to all managers.
To query access you will need a five table join, but you are only selecting one permision attribute.

Categories