Search code examples
laravelauthenticationlaravel-4user-management

Laravel Multi-level hierarchical user system


I have an app using Laravel as the back-end API and AngularJS as the front-end, with a multi-tiered user tree, where users "own" groups of other users.

For instance there may be an owner who owns supervisors, who in turn own employees.

The employees have "walls" with posts and comments. Only employees have walls. Any user in his tree branch may view/post/comment on his wall - so his direct supervisor and the owner have access to his wall.

I'd like this to be extendable in the future to add more "roles" in between, so I don't want to have separate tables for each user type.

I've looked at self-reflected models, where the users table has a parent_id column. I was having a difficult time as the Auth::user->with('children') is returning all users, ignoring the relationship set up in the model:

public function children() {
  return $this->hasMany('User', 'parent_id');
}

public function parent() {
  return $this->belongsTo('User', 'parent_id');
}

The question is this - is there a package available that allows me to scope queries automatically by these hierarchical user relationships?

Or what advice do you have for a user paradigm like this? All searches I've tried and packages I've looked at lead nowhere. I think using a nested sets package is too complicated for this task. None of the auth packages I've looked at truly fit this paradigm. They allow roles and permissions, but don't scope permissions based on parent-child relationships.


Solution

  • For the time being, a hard-coded solution that works is to add a children relationship to the User model:

    public function children() {
      return $this->hasMany('User', 'parent_id');
    }
    

    ...and in the AuthController (where I want the children returned):

    $children = Auth::user()->children()->with('children', 'children.children')->get();
    

    This gives 3 levels deep and can easily be extended (although not by just adding to the database) by adding 'children.children.children'.

    I can also check if it's an employee (the lowest level of the hierarchy) with:

    if(empty($children->toArray()) {}