【发布时间】:2021-05-16 03:55:19
【问题描述】:
我想在三个模型之间建立关系。我的模型是
用户
-- 数据库结构
id
name
---
书籍
-- 数据库结构
id
name
书架
-- 数据库结构
id
name
1:用户有很多书,书属于很多用户
2:用户的书属于一个书架,用户的书架有很多书。
如何定义这三个模型之间的关系?我正在构建一个类似于 Goodreads 的应用程序。
【问题讨论】:
我想在三个模型之间建立关系。我的模型是
用户
-- 数据库结构
id
name
---
书籍
-- 数据库结构
id
name
书架
-- 数据库结构
id
name
1:用户有很多书,书属于很多用户
2:用户的书属于一个书架,用户的书架有很多书。
如何定义这三个模型之间的关系?我正在构建一个类似于 Goodreads 的应用程序。
【问题讨论】:
您的User 和Book 之间存在many to many 关系,Book 和BookShelf 之间存在many to many。
这种类型的关系在后台由pivot 表管理,因此您需要两个数据透视表。
在用户和图书之间切换
php artisan make:migtration create_book_user_table
public function up()
{
Schema::create('book_user', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('user_id')->constrained();
$table->foreignId('book_id')->constrained();
});
}
在书和书架之间切换
php artisan make:migtration create_book_book_shelf_table
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();
});
}
通过创建数据透视表,您可以将关系添加到模型中。
用户
public function books()
{
return $this->belongsToMany(Book::class);
}
图书
public function users()
{
return $this->belongsToMany(User::class);
}
public function bookshelves()
{
return $this->belongsToMany(BookShelf::class);
}
书架
public function books()
{
return $this->belongsToMany(Book::class);
}
现在您有了自己的关系,您可以通过 User 访问它们。举个例子:
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
上面将遍历每个Book 的$user,然后遍历每个与Book 相关的BookShelves。
如果Book 只能属于一个Bookshelf,则需要更改books 表。
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name');
$table->foreignId('bookshelf_id')->constrained('book_shelves');
});
}
您还需要更改 Book 模型上的关系:
public function bookshelf()
{
return $this->belongsTo(BookShelf::class);
}
这样Book 现在只能属于one Bookshelf。
如果User 只能有one Bookshelf,您需要再次更改book_shelves 表:
public function up()
{
Schema::create('book_shelves', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('name');
$table->foreignId('user_id')->constrained();
});
}
然后将关系添加到您的User。
public function bookshelf()
{
return $this->hasOne(BookShelf::class);
}
然后您应该能够直接访问Bookshelf 以获得User。
$user->bookshelf->books
【讨论】:
让我们从第一个任务开始:
1:用户有很多书,书属于很多用户
在这种情况下,它是多对多关系。要实现此设置,您需要像这样的用户表:
用户:id、姓名、其他数据
那么你需要书桌:
书籍:id、姓名、书籍数据
然后你需要第三张表将它们多对多地连接起来:
users_books:id、book_id、user_id
在这种情况下,当您需要属于某个用户的所有书籍时,您可以从 users_books 中选择 user_id=someuserid 并将其加入 books 表,您将收到属于某个用户的所有书籍。
反之亦然,您可以接收拥有某些特定书籍的所有用户。
2:用户的书属于一个书架,用户的书架有很多书。
为此,您必须创建表书架:id、名称
并将外键添加到书籍表中作为 bookshelf_id
那么你的书架将如下所示:
书籍:id、名称、bookdata、bookshelf_id。
因此,当您需要从书架上获取所有书籍时,只需从 bookshelf_id = someid 的书籍中过滤选择
【讨论】:
1:用户有很多书,书属于很多用户
User 有一个 Many To Many relationship 和 Book
// User model
public function books()
{
return $this->belongsToMany(Book::class, 'book_user');
}
Book 有一个 Many To Many relationship 和 User
// Book model
public function users()
{
return $this->belongsToMany(User::class, 'book_user');
}
2:用户的书属于很多书架,书架有很多书。
Book 有一个 Many To Many relationship 和 Bookshelf
// Book model
public function bookshelves()
{
return $this->belongsToMany(Bookshelf::class, 'book_bookshelf');
}
Bookshelf 有一个 Many To Many relationship 和 Book
// Bookshelf model
public function books()
{
return $this->belongsToMany(Book::class, 'book_bookshelf');
}
您需要两个数据透视表。
book_user
| column | migration |
|---|---|
| id | $table->id() |
| book_id | $table->foreignId('book_id')->constrained('books') |
| user_id | $table->foreignId('user_id')->constrained('users') |
book_bookshelf
| column | migration |
|---|---|
| id | $table->id() |
| book_id | $table->foreignId('book_id')->constrained('books') |
| bookshelf_id | $table->foreignId('bookshelf_id')->constrained('bookshelves') |
【讨论】: