Skip to content

Instantly share code, notes, and snippets.

@KoljaL
Created October 26, 2023 15:42
Show Gist options
  • Save KoljaL/68534ab358934da2100d9ecc5a7f5541 to your computer and use it in GitHub Desktop.
Save KoljaL/68534ab358934da2100d9ecc5a7f5541 to your computer and use it in GitHub Desktop.
Multiple User groups in Laravel

For my Laravel App, I need two types of Users: Staff & Member. Some Staff-User has an "is_admin" flag for more rights.

My first attempt was to create two new User-like Models. But as I found out, and it was recommended to me, that is not the common way.

So now I use the User-Model only for the Login (email, name, password & role) and to divide the User-Types by a role field. That worked very well for the login procedure.
But if it's necessary to edit some fields of one of the User-Type, it is getting complicated, because there are always two Models to handle.
This is my code to create a new Member, for example:

public function store(Request $request) {
    $request->validate([
        'name' => 'required',
        'email' => 'required|email',
    ]);
    $authUser = Auth::user();

    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => bcrypt('password'),
        'role' => 'member',
    ]);

    if ($user && $user->id) {
        $location_id = getLocationId($authUser); // get the location_id of the staff member who created the member

        $member = new Member([
            'phone' => $request->phone ?? '',
            'location_id' => $location_id,
            'jc_number' => $request->jc_number ?? '111',
            'max_booking' => getMaxBooking($location_id),
            'active' => 1,
            'archived' => 0,
            'staff_id' => getStaffId($authUser),
        ]);
        dd($member);

        $user->member()->save($member);
        return $member;
     
    } else {
        return response()->json(['message' => 'User creation failed.'], 500);
    }


    // this fails, because the user_id is not set...
    // $member = Member::create([
    //     'user_id' => $user->id,
    //     // 'user_id' => function () {
    //     //     return User::factory()->create()->id;
    //     // },
    //     'phone' => $request->phone ?? '',
    //     'location_id' => getLocationId($authUser),
    //     'jc_number' => $request->jc_number ?? '',
    //     'max_booking' => $request->max_booking ?? '',
    //     'active' => 1,
    //     'archived' => 0,
    //     'staff_id' => getStaffId($authUser),
    // ]);
}

The return is a nested object, with the User fields on level-one and the member-fields on level two. There are two different Id's, in the User level, and in the Member level (and the user_id in Member). And each Model hat the timestamps() (created_at & updated_at).

Almost everywhere, I need the Name from the User-Model and some fields from the Member- or Staff-Model. So I would prefer a way, which allows getting ALL fields from a User wist just one function.

If I use, my first attempt, and make two separated Models for Staff & Member and do not use the default User-Model, it will probably work this way. Or if I create all fields for Staff and for Member in the User-Model and just separate them only by the role-field, too.

But it seems that this two ways are no common use.
Although I can't imagine, that the issues that I have with my current attempt, are the "normal" way.

What I want is relatively simple:

  • two separated types of users
  • they can have the same login route
  • all other routes can (should) be different
  • the class "new Member" should create a full new Member, without dealing with any other Model.
  • if I need all Bookings from a Member, or all Member from a Staff I would like to use: Member::booking() or $staff->member.
  • if a Member has to be deleted: $member->delete() should work.

I don't need a complete solution, a direction in which I can get closer to my goal is enough for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment