Home » Php » php – Laravel 6: how do I send user_id with role_id(s) to controller, in order to sync user_role pivot table?

php – Laravel 6: how do I send user_id with role_id(s) to controller, in order to sync user_role pivot table?

Posted by: admin February 25, 2020 Leave a comment

Questions:

I’m pretty new to Laravel and need help. I’m creating an admin page where users can be assigned multiple roles by means of checkboxes. I have the usual many-to-many relationships set up and a pivot table, “roles_users” with two columns: role_id and user_id. Users’ various roles display fine, but I’m having trouble with the update function. My form sends an array of roles to [email protected], but of course they need to be associated with users — and I can’t figure out how to do that.

Here’s my form:


        <form method="POST" action="{{ route('admin.update') }}" enctype="multipart/form-data">
        {{ csrf_field() }}
        <table>
            <thead>
                <th>Name</th>
                <th>Email</th>
                @foreach ($roles as $role)
                <th>{{ $role->name }}</th>
                @endforeach
            </thead>
            <tbody>
                @foreach ($users as $user)
                <tr>
                    <td>{{ $user->name }}</td>
                    <td>{{ $user->email }}</td>
                    <input type="hidden" name="user[]" value="{{ $user->id }}">
                    @foreach($roles as $role)
                        <td><input type="checkbox" name="roles[]" value={{ $role->id }}
                            @if (in_array($role->id, $user->roles->pluck('id')->toArray() ))
                                checked ="1"
                            @endif />
                        </td>
                    @endforeach
                </tr>
                @endforeach
            </tbody>
        </table>
        <input type="submit" class="tableSubmit" value="Update" />

Here’s my update method:

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

        $id = $request->input('user');
        $user = User::with('roles')->find($id);
        $user->roles()->sync(($request->roles), false);

        return redirect('/admin');
    }

This all throws an error, “Method Illuminate\Database\Eloquent\Collection::roles does not exist.” But of course I do have a roles() method in my User model:

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

How do I pass through the user_id with the roles’ ids, so that the sync method works? Thanks in advance for any help!

How to&Answers:

Here’s my revised update method. It seems to work. I wonder if there’s a more elegant solution, one that doesn’t need a “foreach”?

    public function update(Request $request) {

        $users = (array_keys($request->roles)); // gets the user ids

        foreach($users as $u) {
            $user = User::find($u);
            $user->roles()->sync(array_values($request->roles[$u]));
        }

        return redirect('/admin');
    }
}

Answer:

Your problem is that you are using the with method directly to the collection, the correct way is:

$user = User::where('id',$id)->with('roles')->first();

Hope it works!

EDIT:

Not sure why is a “false” after the array inside the sync method, try changing to this:

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