Skip to content
Branch: master
Find file Copy path
Find file Copy path
1 contributor

Users who have contributed to this file

executable file 147 lines (104 sloc) 4.28 KB

Foobooks: Many to Many

The following is a rough outline of modifications I'll make to Foobooks during Week 13’s lectures.

This should not be considered a stand-alone document; for full details please refer to the lecture video and the Foobooks code source.

Tags in the Edit Book feature

We have everything set up for a tags feature— migrations, seeders, models— now let’s look at how we’d implement tags.

Starting with the Edit Book feature, we need a way to associate tags with books. For authors, this was done with a dropdown which worked because each book can have only one author.

Each book can have many tags, though, so a dropdown won’t do. Instead, let’s show all possible tags with checkboxes. Example of what we’re aiming for:

Tags checkboxes

To accomplish this, we’ll need to gather the following data:

  1. All the possible tags
  2. All the tags associated with the book we're looking at.

To get all the possible tags, we’ll create a getForCheckboxes() method in the Tag model (this way we can reuse this code in the Add a book feature as well).

# Tag.php

public static function getForCheckboxes()
    return self::orderBy('name')->select(['name', 'id'])->get();

Then update BookController@edit to get all the possible tags and the tags associated with this book:

# BookController.php

public function edit($id = null)
    # Get this book and eager load its tags
    $book = Book::with('tags')->find($id);

    if (!$book) {
        return redirect('/book')->with('alert', 'Book not found');

    # Get authors
    $authors = Author::getForDropdown();

    # Get all the possible tags so we can include them with checkboxes in the view
    $tags = Tag::getForCheckboxes();

    # Get just the tag names for tags associated with this book;
    # will be used in the view to decide which tags should be checked off
    $bookTags = $book->tags->pluck('id')->toArray();

    return view('book.edit')
            'book' => $book,
            'authors' => $authors,
            'tags' => $tags,
            'bookTags' => $bookTags,

Use this array of tags to construct the checkboxes in the view:

# /resources/views/book/edit.blade.php

# [...]

@foreach($tags as $tag)
    <ul class='tags'>
                    {{ (in_array($tag->id, $bookTags)) ? 'checked' : '' }}
                    value='{{ $tag->id }}'>
                {{ $tag->name }}

# [...]

In BookController@update where we save the updates, sync the tags from the request:

public function update(Request $request, $id)
    # [...validation removed for brevity...]

    # Find and update book
    $book = Book::find($request->id);

    # Sync the tags
    $book->tags()->sync($request->tags); # <--- NEW CODE

     # Update other book data
    $book->title = $request->title;
    $book->published_year = $request->published_year;
    $book->author_id = $request->author_id;
    $book->cover_url = $request->cover_url;
    $book->purchase_url = $request->purchase_url;

    # Save edits

    # [...finish removed for brevity..]

Tags in the Add a Book feature


Revisiting the book delete feature

Now that books are associated with tags, you'll get a foreign key constraint SQL error when trying to delete a book. To fix, you want to remove any tag associations before the book is deleted...

public function delete(Request $request)
    $book = Book::find($id);

    if (!$book) {
        return redirect('/books')->with('alert', 'Book not found');



    return redirect('/books')->with('alert', $book->title.' was removed.');
You can’t perform that action at this time.