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

Time:11-15

I am creating an online bookstore in Laravel, and upon creating a new book, the administrator is able to define which warehouses that are able to stock this book, by checking the specific warehouses checkboxes. To give insight in how it works, this is my create function:

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']
    ));
}

and my store method:

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);
    }
}

But when an administrator edits a book, the checkboxes that were checked upon creating the book, should be "checked", and the administrator should be able to attach more warehouses, and be able to "unselect" a warehouse, so if an already checked value gets unchecked and sumbitted, it should get detached from the many-to-many table.

This is what i currently have: My edit method:

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']));
}

And my update method:

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);
    }
}

And the checkboxes in my edit.blade view:

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

My Book model:

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

And my warehouse model:

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

Any help on being able to attach / detach upon editing an existing book, would be highly appreciated!

CodePudding user response:

Try this on create and update method for storing

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

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

Update 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
  • Related