Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

austenc's avatar

How would you refactor this? Multiple-role user system

I'm doing some heavy refactoring of the user system in a large application and just looking for opinions on how others might go about it. The original system was designed where users could only have a single role and as such, each role had a mutually exclusive model associated with it. Currently, these models / tables exist:

 - Students
 - Instructors
 - Actors
 - Users

The application uses Confide / Entrust to handle roles and permissions. The users table is central and each record has a polymorphic relation to another table (such as Students or Actors). The goal of the refactor is to have everything in one spot... a Persons table. Since, ultimately, a Student may also be an Actor at the same time.

So I'm making my way along and have created a migration and Person model. Each of the individual models (Student, Actor, etc...) have functions like this:

    public function addWithInput()
    {
        $firstname = Input::get('first');
        $lastname  = Input::get('last');

        // Create a new user
        $user = new User;
        $username = $user->unique_username($lastname, $firstname);
        $user->email                 = Input::get('email');
        $user->username              = $username;
        // randomly generate a user password
        $newPwd = str_random(8);
        $user->password              = $newPwd;
        $user->password_confirmation = $newPwd;
        $user->client                = Config::get('client.abbrev');
        // To require accounts to be confirmed via email remove this line and change Confide config file
        $user->confirmed = 1;
        $user->save();

        // Setup role
        $role = Role::where('name', '=', 'Actor')->first();
        $user->attachRole($role);

        if($user->id !== NULL)
        {
            $p = new Actor;
            $p->user_id   = $user->id;
            $p->first     = $firstname;
            $p->middle    = $lastname;
            $p->last      = Input::get('last');
            $p->birthdate = Input::get('birthdate');
            $p->address   = Input::get('address');
            $p->city      = Input::get('city');
            $p->state     = Input::get('state');
            $p->zip       = Input::get('zip');
            $p->gender    = Input::get('gender');
            $saved = $p->save();

            // polymorphic rel
            $user->userable_id   = $p->id; 
            $user->userable_type = $p->getMorphClass(); 
            $user->save();

            // Send email notification if email defined
            $this->notifyAccountCreated($p, $newPwd);           

            return $p->id;
        }

        return FALSE;       
    }

Now, I understand this code may not be the best practice in terms of architecture... and that's primarily what I'm looking for suggestions on. My gameplan is to centralize everything and allow the Role(s) a user has to define the rest of the logic associated with a given user type. Would it be beneficial for me to use a repository here? I've watched most of the videos on the subject but am finding it hard to 'think that way'. So, to sum it up, I've got two questions:

  • How might I better structure the code so I don't have these weird functions like addWithInput in my model? Or is this method okay?

  • Each original model (Actor, Student, etc...) may have slightly different relations and methods, should I just lump these methods into the new Person model, or is there another obvious way of structuring all this that I'm missing?

Thanks for any insight you can provide! Let me know if I can clear anything up.

0 likes
2 replies
RayRutjes's avatar

If you're kind of obssessed of structuring your code, I'd recommend you take a look at Domain Driven Development.

It has some answers to your questions, like the notion of bounded contexts that elegantly tackles the representation of the same model in different contexts.

Please or to participate in this conversation.