Reputation: 1828
I have a roles and permissions table in a many to many relationship, and pivot table permission_role
. This issue I am experiencing when trying to update the permissions on the role.
For example: When creating the admin role: I added the permission: view_users
to it. Now when trying to update it, giving it the additional permission create_team
.
The code:
$roleUpdate = Role::where('id', $role->id)->update([
'name' => $request->input('name'),
'updated_at' => Carbon::now()
]);
$permissions = $request->input('permission');
//dd($permissions);
foreach ($permissions as $permission) {
$role->permissions()->sync($permission, true);
}
if ($roleUpdate) {
Alert::toast('Role updated successfully', 'success');
return redirect()
->route('roles.index', ['role' => $role->id])
->with('success', 'Role Updated Successfully');
}
//redirect
return back()->withInput();
When I dd()
on the permission to see which options are coming through, I get the expected and correct result
array:2 [▼
0 => "3"
1 => "4"
]
However, when the data get saved to the database, only the new value is stored and the old one is removed. I understand the issue may be caused by setting detach to true on this line:
$role->permissions()->sync($permission,true);
But if I set it to false, then it doesn't work when I update the role's permission by removing one of the permissions. It doesn't detach. It doesn't seem to work according to the explanation given in the docs on the link below. Not sure what I'm missing Laravel Docs
Upvotes: 4
Views: 90
Reputation: 8252
The problem is that you are using a foreach:
array:2 [▼
0 => "3"
1 => "4"
]
foreach ($permissions as $permission) {
$role->permissions()->sync($permission, true);
}
On the first loop you remove all permissions from the role except the permission with the id 3
, on the second loop you again remove all permissions from the role except the permission with the id 4
, which means you have deleted the previously set permission with id 3
.
Removing the foreach and passing the whole array should work:
// no need to pass 'true' as the second argument as it is the default value
$role->permissions()->sync($request->input('permission'));
From the docs:
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table:
$user->roles()->sync([1, 2, 3]);
Upvotes: 4