Search code examples
phpcheckboxlaravel-8updatecheck

update checkbox value in laravel 8 (blade/ controller )


I'm beginner in laravel and I want to update multiple checkboxes in database .. when I click at update button automatically my inputs show old value also my permissions are checked by old value to update it ..

relation between user and permission is manytomany .. I have another table named userpermissions who has id_user and id_permission

this is my update form in ( edit.blade.php)

<form action="{{ url('users/'.$user->id) }}" method="POST">
                                    @csrf
                                    @method('PUT')
                                    <div class="row">
                                        <div class="col-md-6">
                                            <div class="form-group">
                                                <label>Name</label>
                                                <input type="text" name="name" id="name" required class="form-control" value="{{ $user->name }}">
                                                @error('name')
                                                    <ul class="alert"><li class="text-danger">{{ $message }}</li></ul>
                                                @enderror
                                            </div>
                                        </div>
                                        <div class="col-md-6">
                                            <div class="form-group">
                                                <label>Email</label>
                                                <input type="email" name="email" id="email" required class="form-control" value="{{ $user->email }}">
                                            </div>
                                        </div>
                                        <div class="col-md-12">
                                            <div  class="form-group">
                                            @foreach($permissions as $permission)
                                                <input type="checkbox" name="data[]" value="{{ $permission->id }}"
                                                <?php if( in_array($permission->id, $user->userPermissions->pluck('permission_id')->toArray())){ echo 'checked="checked"'; } ?>/>
                                               {{ $permission->name }}
                                                @if($loop->iteration % 3 == 0 ) <br> @else @endif
                                                @endforeach
                                            </div>
                                        </div>

                                    </div>
                                    <div class="text-right mt-4">
                                        <button type="submit" class="btn btn-primary"> Add</button>
                                    </div>
                                </form>

and this is my controller where I think have a problem with methods :

edit function

 public function edit(User $user)
{
    $permissions = Permission::get();
    return view('users.edit', compact('user','permissions'));
}

update function :

public function update(UserRequest $request,User $user)
{
    $user->update(
        $request->only('name', 'email')
    );
    $user->userPermissions()->save($request->input('data'));
    return redirect()->back()->with('status','user updated !');
}

and this is my functio store :

public function store(UserRequest $request)
{
    $this->validate($request, [
        'name' => 'required',
        'email'=>'required|email',
        'password' => 'required|confirmed|min:6',
    ]);
    $user = User::create(
        $request->only('name', 'email', 'password')
    );
    $user->userPermissions()->createMany($request->input('data'));
    return redirect()->back()->with('status','Utilisateur ajouté !');
}

Thanks for advance !


Solution

  • $user->userPermissions()->save($request->input('data'));
    

    One important thing to understand here, is that save() on relation doesn't remove old values from pivot table, it just add more values to it(no distinction check). You need something like refresh functionality. Look at attaching\detaching or sync, second one is more convenient.

    In first case before saving permissions you can do this

    // remove all old permissions
    $user->userPermissions()->detach();
    // update them with new one
    $user->userPermissions()->attach($request->input('data'));
    

    In second case, which is less verbose then first one you just need to pass and array of permissions to user object.

    // this will do both things which we did before
    $user->userPermissions()->sync($request->input('data'))
    

    But i encourage you to read the docs and ask questions after ;)

    Another thing which i saw and its not related to the current topic is

    $user->userPermissions->pluck('permission_id')->toArray()
    

    you are using lazy load inside of foreach loop which means that on each iteration of the loop you are making a query to the database(N + 1 problem). You can preload/eager load userPermissions instead of loading them on a fly by declaring with relation in your User model like this

    class User extends Model
    {
        /**
         * The relationships that should always be loaded.
         *
         * @var array
         */
        protected $with = ['userPermissions'];
        ...
    }
    

    and then in your User object will have userPermissions property which you can compare to permissions.

    Hope that you get main idea and info was useful for you!