【问题标题】:How to setup relationship between 3 Model in Laravel?如何在 Laravel 中设置 3 个模型之间的关系?
【发布时间】:2020-10-12 19:32:17
【问题描述】:

我知道有很多类似的问题,但我找不到更好的答案。 让我们进入正题。

我有 3 个表格,模型如下所示:

//******* academic_years table**************
Schema::create('academic_years', function (Blueprint $table) {
        $table->id();
        $table->string('year')->unique();
    });
//************classrooms table*************
Schema::create('classrooms', function (Blueprint $table) {
        $table->id();
        $table->string('name')->unique();
        $table->string('slug');
    });
//**********faculties table***************
Schema::create('faculties', function (Blueprint $table) {
      $table->id();
      $table->string('name')->unique();
      $table->string('slug');
    });

我想在这些模型之间建立多对多关系:

  1. 一学年(2020)有很多教室
  2. 当年(2020 年)的每个教室可以有多个学院
  3. 一个教师可以属于多个教室。

我想建立一个关系,允许返回所有年份的列表,以及属于每个教室的教室和院系。

例如:我想用教室返回 Year:2020:Grad-1 和 Faculty-1,Grad-2 和 Faculty-1

我的数据透视表如下所示。或者也许有人可以提出更好的方法。

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    我建议在教室和院系表中添加外键。

    之后你需要在每个模型之间分配添加关系,belongsToMany() 和 hasMany()。

    定义后,您可以使用with()whereHas 获取相关数据。

    获取您将使用的所有教室和学院:

    AcademicYear::with('classroom.faculty')
      ->where('year', 2020);
    

    我想用教室返回 Year:2020:Grad-1 和 Faculty-1,Grad-2 和 Faculty-1

    AcademicYear::with('classroom.faculty')
      ->whereHas('classroom', function($query) {
        $query->whereIn('name', ['Grad-1', 'Grad-2']);
          ->whereHas('faculty', function($query) {
            $query->where('name', 'faculty-1');
          });
      })
      ->where('year', 2020);
    

    您还应该能够执行以下操作(不确定查询会如何查找):

    AcademicYear::with([
        'classroom' => function($query) {
          $query->whereIn('name', ['Grad-1', 'Grad-2']);
        },
        'faculty' => function($query) {
          $query->where('name', 'faculty-1');
        })
      ])
      ->where('year', 2020);
    

    参考 - https://laravel.com/docs/7.x/eloquent-relationships#constraining-eager-loads

    而且...如果您要坚持使用相同的结构,您可以定义相同的关系,hasManyThrough,但通过您的数据透视表。


    更新:

    您可以做的另一件事是为您的数据透视表添加一个模型并定义数据透视表与其他模型之间的关系。

    我想用教室返回 Year:2020:Grad-1 和 Faculty-1,Grad-2 和 Faculty-1

    MyPivotModel::with([
        'academic_year', 
        'classroom', 
        'faculty'
      ])
      ->whereHas('classroom', function($query) {
        $query->whereIn('name', ['Grad-1', 'Grad-2']); 
      })
      ->whereHas('faculty', function($query) {
        $query->where('name', 'faculty-1');
      })
      ->whereHas('academic_year', function($query) {
        $query->where('year', 2020);
      });
    

    【讨论】:

    • 非常感谢您的回复。我可以在教室和学院表上添加外键,但我不想这样做的原因是教室将被分配到多个学年,与学院相同。我想保留所有学年的记录。如果我有这些表的外键,则意味着如果我在学院表中有classic_id 外键,它将引用单个教室并且与教室表相同。 我想让一个教员分配到多个教室和分配到不同年份的教室
    • 好的,很酷。另一种方法是使用manyToMany。这样你就可以使用 Laravel 自带的 sync() 和 attach()/detach() 方法。需要注意的一件事是,在索引具有空值的列时,MySQL 可能会表现得很奇怪。
    【解决方案2】:

    我能够在路上解决这个问题。也许这不是最好的方法,但我至少把我带到了某个地方。如果有人有更好的方法或这种方法存在一些问题,请随时在此处分享。

    我将关系设置如下:

    //*********ACADEMICYEAR MODEL *************
    
    public function classrooms()
    {
      return $this->belongsToMany('App\Model\Setting\Classroom', 'academic_year_classroom);
    }
    
    
    //***********FACULTY MODEL ********************** //
    public function classrooms()
    {
      return $this->belongsToMany('App\Model\Setting\Classroom', 'academic_year_classroom');
    }
    
    
    //********CLASSROOM MODEL **************
    public function academicyears()
    {
      return $this->belongsToMany('App\Model\Setting\AcademicYear');
    }
    
    public function faculties()
    {
      return $this->belongsToMany('App\Model\Setting\Faculty', 'academic_year_classroom', 'classroom_id', 'faculty_id');
    }
    
    //1. I was able to return the records for a single year with it classrooms and faculties assigned to that classroom as follow:
    
    public function show($id)
    {
      return $year = AcademicYear::with(['classrooms', 'classrooms.faculties' => function ($q) use($id) {
        $q->where('academic_year_id', $id);
      }])->findOrFail($id);
    }
    

    我还能够返回所有年份的列表,每个年份的教室以及分配给每个教室的学院如下:

       public function index()
      {
       // First I retrieve all the Year IDs as an array
        $yearID = AcademicYear::pluck('id')->toArray();
    
        foreach($yearID as $yr) {
          $year = AcademicYear::with(['classrooms', 'classrooms.faculties' => function ($q) use($yr) {
            $q->whereIn('academic_year_id', [$yr]);
          }])->orderBy('year', 'DESC')->get();
        }
          return $year;
      }
    

    同样,如果您有更好的方法来解决这个问题,请与我们分享。如果这个答案有帮助,请投票,以便它可以帮助其他人。谢谢。

    【讨论】:

      猜你喜欢
      • 2018-10-17
      • 1970-01-01
      • 2019-10-06
      • 1970-01-01
      • 2016-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-23
      相关资源
      最近更新 更多