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

andyz's avatar
Level 9

Model extending users

In my project I have a users table, a roles table and a pivot table role_user, which defines which is the role of every user. Of course there are corresponding models, User and Role. Now, I would like to have a Client model, which will load only the users that have the role of Client. (role_id = 4). Is that possible and how can I do it?

0 likes
10 replies
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

Why not just add a scope?

User::clients()->get();

//on model
public function scopeClients($query)
    {
        return $query->whereHas('role', function (Builder $subquery) {
                 $subquery->where('role'_id,  4);
       });
    }
andyz's avatar
Level 9

Thank you, @sinnbeck. That seems like a good idea. I thought it would be nice to use Client::whatever_function when referring to clients. Is that possible with scope?

andyz's avatar
Level 9

@Sinnbeck I still have a problem and would much appreciate some more help. I created a ClientScope and in the apply() method added:

$builder->whereHas('roles', function(Builder $subquery){
                    $subquery->where('role_id', 4);
                });

but when I call Client::all() the query is wrong, because instead of looking for user_role table, its is looking for client_role. The query is

select * from `users` where exists (select * from `roles` inner join `client_role` on `roles`.`id` = `client_role`.`role_id` where `users`.`id` = `client_role`.`client_id` and `role_id` = 4)) 

Any idea on how I can fix that?

Sinnbeck's avatar

@andyz So it should just be this I would assume

$builder->whereHas('roles', function(Builder $subquery){
                    $subquery->where('roles.id', 4);
                });
Sinnbeck's avatar

Or you can just add your own join

$builder->join('client_roles', function($join){
     $join->on('users.id', '=', 'client_role.user_id')->where('client_role.role_id', 4);

                });
Sinnbeck's avatar

Oh yeah, one last thing. Consider not extending User. Instead I would use traits for shared methods.

andyz's avatar
Level 9

@Sinnbeck That was it! In fact the whole function is

public function apply (Builder $builder, Model $model)
     {
        $builder->join('role_user', function($join){
            $join->on('users.id', '=', 'role_user.user_id')
                ->where('role_user.role_id', 4);
        });
        
     }

Thanks for saving!

Please or to participate in this conversation.