【问题标题】:Laravel Many To Many Relationship between Three ModelsLaravel 三个模型之间的多对多关系
【发布时间】:2021-05-16 03:55:19
【问题描述】:

我想在三个模型之间建立关系。我的模型是

用户

-- 数据库结构

  id

  name

  ---

书籍

-- 数据库结构

  id

  name

书架

-- 数据库结构

  id

  name

1:用户有很多书,书属于很多用户

2:用户的书属于一个书架,用户的书架有很多书。

如何定义这三个模型之间的关系?我正在构建一个类似于 Goodreads 的应用程序。

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    您的UserBook 之间存在many to many 关系,BookBookShelf 之间存在many to many

    这种类型的关系在后台由pivot 表管理,因此您需要两个数据透视表。

    在用户和图书之间切换

    1. 创建您的迁移
    php artisan make:migtration create_book_user_table
    
    1. 定义您的关系
    public function up()
    {
        Schema::create('book_user', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
            $table->foreignId('user_id')->constrained();
            $table->foreignId('book_id')->constrained();
        });
    }
    

    在书和书架之间切换

    1. 创建您的迁移
    php artisan make:migtration create_book_book_shelf_table
    
    1. 定义您的关系
    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
    

    【讨论】:

    • 我已更新问题以便更好地理解。请再过一遍。
    【解决方案2】:

    让我们从第一个任务开始:

    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 的书籍中过滤选择

    【讨论】:

      【解决方案3】:

      1:用户有很多书,书属于很多用户

      • User 有一个 Many To Many relationshipBook
        • // User model
          public function books()
          {
              return $this->belongsToMany(Book::class, 'book_user');
          }
          
      • Book 有一个 Many To Many relationshipUser
        • // Book model
          public function users()
          {
              return $this->belongsToMany(User::class, 'book_user');
          }
          

      2:用户的书属于很多书架,书架有很多书。

      • Book 有一个 Many To Many relationshipBookshelf
        • // Book model
          public function bookshelves()
          {
              return $this->belongsToMany(Bookshelf::class, 'book_bookshelf');
          }
          
      • Bookshelf 有一个 Many To Many relationshipBook
        • // Bookshelf model
          public function books()
          {
              return $this->belongsToMany(Book::class, 'book_bookshelf');
          }
          

      您需要两个数据透视表。

      book_user

      column migration
      id $table-&gt;id()
      book_id $table-&gt;foreignId('book_id')-&gt;constrained('books')
      user_id $table-&gt;foreignId('user_id')-&gt;constrained('users')

      book_bookshelf

      column migration
      id $table-&gt;id()
      book_id $table-&gt;foreignId('book_id')-&gt;constrained('books')
      bookshelf_id $table-&gt;foreignId('bookshelf_id')-&gt;constrained('bookshelves')

      【讨论】:

      • 我已更新问题以便更好地理解。请再过一遍。
      • 我的答案保持不变。
      • 好的。这样我就能拿到用户的书架了?如果是,那么 laravel 怎么知道我们询问的是与用户的关系,而不是与当前书籍的关系?
      猜你喜欢
      • 2020-03-27
      • 1970-01-01
      • 2018-05-23
      • 1970-01-01
      • 2020-10-05
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多