You have a many to many
relationship between your User
and Book
, as well as a many to many
between your Book
and BookShelf
.
This type of relationship is managed by a pivot
table behind the scenes, so you will require two pivot tables.
Pivot between User and Book
- Create your migration
php artisan make:migtration create_book_user_table
- Define your relationship
public function up()
{
Schema::create('book_user', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('user_id')->constrained();
$table->foreignId('book_id')->constrained();
});
}
Pivot between Book and BookShelf
- Create your migration
php artisan make:migtration create_book_book_shelf_table
- Define your relationship
public function up()
{
Schema::create('book_user', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('book_id')->constrained();
$table->foreignId('book_shelf_id')->constrained();
});
}
With the pivot tables create you can add the relationships to your models.
User
public function books()
{
return $this->belongsToMany(Book::class);
}
Book
public function users()
{
return $this->belongsToMany(User::class);
}
public function bookshelves()
{
return $this->belongsToMany(BookShelf::class);
}
BookShelf
public function books()
{
return $this->belongsToMany(Book::class);
}
Now you have your relationships, you can access them on your User
. As an example:
Route::get('/', function () {
$user = User::where('id', 1)->with(['books', 'books.bookshelves'])->first();
return view('user', compact('user'));
});
user.blade.php
<h3>{{ $user->name }}</h3>
<h4>Books</h4>
@foreach ($user->books as $book)
<h5>{{ $book->name }}</h5>
<p>Can be found on @choice('shelf|shelves', $book->bookShelves()->count())</p>
@foreach ($book->bookShelves as $shelf)
<li>{{ $shelf->name }}</li>
@endforeach
@endforeach
The above would iterate over each Book
for the $user
and then iterate over each of the BookShelves
that Book
is related to.
Update
If a Book
can only belong to one Bookshelf
, you need to alter your books
table.
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name');
$table->foreignId('bookshelf_id')->constrained('book_shelves');
});
}
You will also need to alter the relationship on your Book
model:
public function bookshelf()
{
return $this->belongsTo(BookShelf::class);
}
This way a Book
can now only belong to one
Bookshelf
.
If a User
can only have one
Bookshelf
, again you need to alter your book_shelves
table:
public function up()
{
Schema::create('book_shelves', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name');
$table->foreignId('user_id')->constrained();
});
}
Then add the relationship to your User
.
public function bookshelf()
{
return $this->hasOne(BookShelf::class);
}
You should then be able to access the Bookshelf
for a User
directly.
$user->bookshelf->books