使用 Laravel 中多个复选框的 attach() 更新多对多关系数据

Updating many-to-many relational data with attach() from multiple checkboxes in Laravel

我正在 Laravel 中创建一个在线书店,在创建一本新书后,管理员可以通过选中特定仓库复选框来定义哪些仓库可以存放这本书。 为了深入了解它的工作原理,这是我的创建函数:

public function create()
{
    $authors = Author::all();
    $selectedAuthor = Book::first()->author_id;

    $publishers = Publisher::all();
    $selectedPublisher = Book::first()->publisher_id;

    $warehouses = Warehouse::all();
    $selectedWarehouse = Book::first()->warehouse_id;

    return view('books.create', compact(['authors', 'publishers', 'warehouses'],
                    ['selectedAuthor', 'selectedPublisher', 'selectedWarehouse']
    ));
}

和我的存储方法:

public function store(Request $request)
{
    $request->validate([
        'ISBN' => 'required',
        'author_id' => 'required',
        'publisher_id' => 'required',
        'year' => 'required',
        'title' => 'required',
        'price' => 'required',
    ]);

    try {
        $book = Book::create($request->all());

        foreach ($request->checked as $value){
            $book->warehouses()->attach([$value]);
        }

        return redirect()->route('books.index')
            ->with('success','Book created successfully.');

    } catch (\Illuminate\Database\QueryException $e) {
        var_dump($e->errorInfo);
    }
}

但是当管理员编辑一本书时,创建这本书时选中的复选框应该被“选中”,并且管理员应该能够附加更多的仓库,并且能够“取消选择”一个仓库,因此,如果一个已经检查的值未被检查并被提交,它应该从多对多 table.

中分离出来

这是我目前拥有的: 我的编辑方法:

public function edit(Book $book)
{
    $authors = Author::all();
    $selectedAuthor = Book::first()->author_id;

    $publishers = Publisher::all();
    $selectedPublisher = Book::first()->publisher_id;

    $warehouses = Warehouse::all();
    $selectedWarehouse = Book::first()->warehouse_id;

    return view('books.edit', compact(['book', 'authors', 'publishers', 'warehouses'],
                    ['selectedAuthor', 'selectedPublisher', 'selectedWarehouse']));
}

还有我的更新方法:

public function update(Request $request, Book $book)
{
    $request->validate([
        'ISBN' => 'required',
        'publisher_id' => 'required',
        'author_id' => 'required',
        'year' => 'required',
        'title' => 'required',
        'price' => 'required',
    ]);

    try {
    $book->update($request->all());

    // TODO: Update warehouses

        return redirect()->route('books.index')
            ->with('success','Book updated successfully.');

    } catch (\Illuminate\Database\QueryException $e) {
        var_dump($e->errorInfo);
    }
}

我的 edit.blade 视图中的复选框:

@foreach($warehouses as $warehouse)
    <input type="checkbox" name="checked[]" value="{{ $warehouse->id }}">
    {{ $warehouse->address }}
    <br/>
@endforeach

我的书本型号:

public function warehouses()
{
    return $this->belongsToMany(Warehouse::class);
}

还有我的仓库模型:

public function books()
{
    return $this->belongsToMany(Book::class);
}

任何有关在编辑现有书籍时能够附加/分离的帮助,将不胜感激!

尝试创建和更新存储方法

// Your method
foreach ($request->checked as $value){
    $book->warehouses()->attach([$value]);
}

// Try This
$book->warehouses()->sync($request->checked); // $request->checked must be an array

更新Blade

@foreach($warehouses as $warehouse)
    <input @if($book->warehouses()->where('warehouse_id', $warehouse->id)->exists()) checked @endif type="checkbox" name="checked[]" value="{{ $warehouse->id }}">
    {{ $warehouse->address }}
    <br/>
@endforeach

我将根据您的问题为这个示例留一个逻辑。在这种情况下是角色:

public function edit(Role $role){
        //get roles ids
        $permission_role = [];
        foreach($role->permissions as $permission){
            $permission_role[] = $permission->id;
        }
        //get permissions
        $permissions = Permission::all();

        return view("role.edit", compact('role', 'permission_role', 'permissions'));
    }

在blade中:

<div class="row">
    <div class="col-md-8">
        <div class="form-group">
          <label>Select the permissions for the current role</label>
        @foreach ($permissions as $permission)
        <div class="valid-feedback d-block" style="font-size: 15px !important;">
            <input  type="checkbox" value="{{ $permission->id }}" name="permissions[]"
                @if(is_array(old('permissions')) && in_array("$permission->id", old('permissions')))
                        checked
                @elseif(is_array($permission_role) && in_array("$permission->id", $permission_role))
                checked
                @endif>
            <strong> {{ $permission->description }} </strong>
            </div>   
            @endforeach
        </div>

            <div class="invalid-feedback d-block">
            @foreach ($errors->get('permissions') as $error)
                   
                    {{ $error }}
                @endforeach
            </div>
    </div>
</div>

通过这种方式,您还可以在没有内容时保留旧的复选框 select。您应该根据需要对其进行验证。