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

baguus's avatar

Update pivot table once again

Hi I know this question was asked and answered already but I cant find the working solution. I have 3 tables: users, roles, role_user

users model

public function roles()
    {
        return $this
            ->belongsToMany('App\Role')
            ->withTimestamps();
    }

roles model

    public function users()
    {
        return $this
            ->belongsToMany('App\User')
            ->withTimestamps();
    }

controller

public function update(Request $request, $id)
    {

$user = DB::table('users')
            ->where('id', $id)
            ->update([
                'first_name' => $request['first_name'],
                'last_name' => $request['last_name'],
                'email' => $request['email'],
                'companies_id' => $request['companies'],
            ]);

// How to update the record in role_user table?
  
return redirect('/');
}

Is there a simple way to update the record in role_user table? I was trying with detach(), attach(), sync(),...

0 likes
7 replies
bobbybouwmann's avatar
Level 88

It depends on what you post in your controller. If you post all current associated roles with the user the easiest way would be using sync

// Assuming you are posting an array of roles!
$user->roles()->sync($request->get('roles'));

Note: DB::table doesn't return a User model object, so instead you should do this

$user = User::firstOrFail($id);
$user->update([
    'first_name' => $request['first_name'],
    'last_name' => $request['last_name'],
    'email' => $request['email'],
    'companies_id' => $request['companies'],
]);

$user->roles()->sync($request->get('roles'));
1 like
baguus's avatar

Hi Thank you for your answer. I guess I went the wrong way :)

contoller

public function edit(Request $request, $id) {
    $roles = Role::all()->pluck('name', 'id');
    $companies = Companies::all()->pluck('name', 'id');
    $users = DB::table('users')
                ->join('companies', 'users.companies_id', '=', 'companies.id')
                ->join('role_user', 'role_user.user_id', '=', 'users.id')
                ->join('roles', 'roles.id', '=', 'role_user.role_id')
                ->select('users.id', 'users.username', 'users.first_name', 'users.last_name', 'users.email', 'companies.name AS company', 'roles.name AS user_role', 'roles.id AS role_id', 'users.companies_id')
                ->where('users.id', '=', $id)
                ->first();

            return view('users.edit', compact(['users', 'roles', 'companies']));
}



view

{!! Form::open(['action' => ['UsersController@update', $users->id],'class'=> 'form-horizontal']) !!}
{{ csrf_field() }}

<div class="col-md-9">
<input id="name" type="text" class="form-control" name="name" value="{{ $users->username }}" required disabled>

@if ($errors->has('username'))
     <span class="help-block">
        <strong>{{ $errors->first('username') }}</strong>
      </span>
@endif
</div>
.
.
.

<div class="form-group{{ $errors->has('role') ? ' has-error' : '' }}">
  <label for="role" class="col-md-3 control-label">User role</label>
       <div class="col-md-9">
    {{ Form::select('roles', $roles, $users->role_id, ['class' => 'form-control']) }}
       </div>
 </div>

<div class="form-group{{ $errors->has('companies') ? ' has-error' : '' }}">
 <label for="companies" class="col-md-3 control-label">Company</label>
   <div class="col-md-9">
{{ Form::select('companies', $companies, $users->companies_id, ['class' => 'form-control']) }}
  </div>
</div>
.
.
.
<button type="submit" class="btn btn-primary pull-right">Update</button>

{!! Form::close() !!}

baguus's avatar

I think I got it working :)

@bobbybouwmann Is this a typo "$user = User::firstOrFail($id);" ? If so, could you edit your reply so I can accept it as the correct answer? Thank you

controller

public function edit(Request $request, $id) {

// for dropdown items
$companies = Companies::all()->pluck('name', 'id');
$roles = Role::pluck('name','id')->all();

// my user data
$users = User::with('roles','companies')->findOrFail($id);

return view('users.edit', compact(['users', 'roles', 'companies']));
}


public function update(Request $request, $id) {

$user = User::findOrFail($id);
        $user->update([
            'first_name' => $request['first_name'],
            'last_name' => $request['last_name'],
            'email' => $request['email'],
            'companies_id' => $request['companies'],
        ]);

        $user->roles()->sync($request->get('roles'));

    return redirect('users');
}

view


{{ Form::select('roles', $roles, $users->roles()->pluck('roles.id'), ['class' => 'form-control']) }}

baguus's avatar

hmm I must be missing something..

firstOrFail() returns the first record found in the database. If no matching model exist, it throws an error.

So if I understand correctly firstOrFail() does not take an attribute $id If I use firstOrFail($id) i get:

Type error: Argument 1 passed to Illuminate\Database\Grammar::columnize() must be of the type array, string given at Grammar->columnize('6') in Grammar.php (line 131)

findOrFail($id) takes an id and returns a single model. If no matching model exist, it throws an error.

This one works for me. So I would say find is the correct one, not first

If I'm wrong I need more tutoring :)

bobbybouwmann's avatar

Aah yeah of course I mean findOrFail, I typed it wrong in my first reply, but in my second reply it was correct. Sorry for the confusion!

baguus's avatar

Not a problem. I did get the chance to learn the right way to call the model :) I must say though, that I cannot find the example on how to retreive the model with related data (user with user role)

this

$users = User::with('roles','companies')->findOrFail($id);

was a more or less a lucky guess.

Anyway, thank you for your help. I'm sure I'll have more basic questions in the future.

Please or to participate in this conversation.