7

I'm building a Laravel 4 app that requires login authentication for 3 entity types: Coach, Student & Admin, all with separate user interfaces. While I could use a package like Sentry 2 and a single DB user table with user types to achieve this, something about the potential polymorphic DB design patterns and headaches that can occur down the track, don't sit well with me. Having dealt with polymorphic issues in the past with previous apps, and the grief it can create when you want to normalise your DB structure, etc. having separate DB tables for each entity type seems a better way to go.

How would you solve this design problem?

Laravel 4 auth uses basically the following files:

  • Auth.php (facade)
  • AuthManager.php
  • AuthServiceProvider.php
  • Guard.php
  • auth.php (config)
  • User.php (eloquent model)

I've played around with duplicating these files to come up with mostly an independent auth for the coach entity that works, registering the facade and service provider in the app.php file, as well as making the necessary changes to config to use the Coach eloquent model for authentication:

  • AuthCoach.php (facade)
  • AuthCoachManager.php
  • AuthCoachServiceProvider.php
  • Guard.php
  • authcoach.php (config)
  • Coach.php (eloquent model)

I am still using Guard.php from the standard Laravel 4 auth, but Guard can easily be extended if the need arises to customise Guard methods for coach authentication by creating a GuardCoach.php file.

If I'm going to have separate auth for each entity type, do you think this is a good way to achieve it?

Can you see any potential problems or know a better way of doing this?

1

2 Answers 2

3

Maybe I do not understand your context well, but why dont you just use the basic concept of role based access control and render different stuff for different roles ? If that is not tight enough you can use attribute based auth policies to granulate permissions. What are the reasons you want to duplicate (triple that is) auth-logic? Not mentioning the fact of redundant db data (separate user table for separate user type? yuk!) ?

If you are not satisifed with Sentry (personally, I dont use that library) I can recommend Zizaco/Confide + Zizaco/Entrust as a clean and elegant solution for user/role/permission management. Check it out here Zizaco GitHub.

A quick general idea:

  • use a single clean authentication mechanism for whole app
  • granulate access with Roles or Roles+Permissions
  • separate your admin logic into separate controllers (AdminUserController, AdminCoachController, whatever..)
  • I see no difficulties in composing appropriate blade templating structure to have it all nicely done and well organised

What are your polymorphic concerns?

If you are worrying that your user table will get cluttered, leave it be as a place to store auth details and put all other necessary (non-auth) user details in another table.

Hope this helps you out, if only I understood your problem well.

Sign up to request clarification or add additional context in comments.

Comments

3

I think you are trying to swat a mosquito using a mallet.

Here is how I tackled the same problem:

  • I wanted to make sure that each user's authentication (username, password) is stored in the same table. Basically, I had three types of users.

  • I used Sentry 2 which makes it a breeze to manage the authentication stuff.

  • Using the default migrations provided by Sentry 2, I added a column 'role' to the 'users' table - which differentiates the 3 types of users.

  • For each user type, I created a table with specific fields.

  • When the user authenticated, I would grab their 'role' from the 'users' table, run a few if statements and know which view to serve them.

And the mosquito was completely dead.

Onto yours:

  • Basically, both our approaches are the same - since each user type has a separate table for fields they don't all share (except first name, last name, email, password, last login etc).

  • Your approach will allow a user to belong to the three entities - which is logically not correct. Mine won't - which is logically...

  • You are afraid of 'polymorphic issues' but I don't think we have a lot to deal with here. All we would perhaps do is define in our models that a coach, for example, belongsTo a user. And a user hasOne coach.

  • But in reality, we don't even need to define the relationships. Because at authentication, we need to run if statements anyway. So, using the user object returned from authentication, we will know two things: which table to then go to for user-type-sepecific information and which view to serve to the authenticated user.

Don't be afraid, son

6 Comments

What ID would you then use as the FK (foreign key) for each user type in the rest of the DB? The the auth table ID, or the user specific table ID?
I would use the user id because I know it's unique for each user. If you use the user-type id, it won't be unique since each user-type has a separate table (coach, student, admin). You don't have to worry about the three tables having foreign keys since they are only complementing the users table. The users table is the 'boss'.
Ok cool. So given this schema, if you have a lesson table, how would you record which coach and student the lesson relates too, considering both user types have a FK user_id? A single relationship ID could also work here, by having a user_parent_child table (id, parent_id (coach user_id), child_id (student user_id)) and recording the user_parent_child_id as the FK in the lesson table. This seems really messy though.
In this case - because a lesson is specific to a coach and a student, you obviously would need to have id|coach_id|student_id etc fields in the lesson table. And then, if you define your user/coach and user/student relationship correctly, to get the Lesson object with info of the student on a given lesson, you would only need to do something like $lesson = Lesson::with('student.user')->get(); for example.
I'll be using innoDB tables setting up FK's to maintain good DB integrity, both coach_id & student_id in the lesson table will have FK's for user_id, which means there will be no DB validation of the user_id types in the lesson table. A coach user type could be recorded in student_id and visa versa. Other DBMS's allow FK constraints to manage this, but as far as I understand, this is very challenging in MySQL. As the DB grows, these integrity issues will become littered everywhere, which comes back to my original concerns with having one users table with a user type classification. Thoughts?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.