Laravel 查询构建器与雄辩的关系

Posted

技术标签:

【中文标题】Laravel 查询构建器与雄辩的关系【英文标题】:Laravel QueryBuilder to Eloquent Relationship 【发布时间】:2019-12-09 12:59:42 【问题描述】:

更新:

我的结果差不多了,我只想过滤我正在寻找的“当前”学生

我更新的模型:

// Student.php
public function enrolled()

    return $this->belongsToMany('App\Clas-s-room', 'inscribed_students')
    ->with('enrolled_steps.student_process')
    ->whereRaw('start_at >= curdate()');


// Clas-s-room.php
public function enrolled_steps()

    return $this->hasMany('App\InscribedStudent');


// InscribedStudent.php
public function student_process()

    return $this->hasMany('App\StudentSelectionProcess');

我的输出 json:


  "id": 1,
  "name": "This is a Student",
  "email": "dborer@example.org",
  "enrolled": [
    
      "id": 31,
      "name": "This is a Clas-s-room",
      "shift": "Morning",
      "enrolled_steps: [
        
          "id": 1,
          "student_id": 1,
          "clas-s-room_id": 1,
          "student_process": [
            
              "id": 1,
              "status": "Approved"   
             
          ]
        ,
        
          "id": 2,
          "student_id": 2,
          "clas-s-room_id": 1,
          "student_process": [
            
              "id": 2,
              "status": "Approved"   
             
          ]
        ,  
      ] 
    
  ]

当前的问题是 enrolled_steps 是返回一个数组,但我过滤了一个学生,我该如何解决它以仅获取我当前的学生?

我的预期输出:


  "id": 1,
  "name": "This is a Student",
  "email": "dborer@example.org",
  "enrolled": [
    
      "id": 31,
      "name": "This is a Clas-s-room",
      "shift": "Morning",
      "enrolled_steps: 
        "id": 1,
        "student_id": 1,
        "clas-s-room_id": 1,
        "student_process": [
          
            "id": 1,
            "status": "Approved"   
           
        ]
       
    
  ]

问题:

我的问题是我必须建立多重/硬性关系才能显示有关学生的信息。

+--------------------+
| Student            | 
+--------------------+
| id                 | 
| name               |
| email              |  
+--------------------+
+--------------------+
| Clas-s-room          | 
+--------------------+
| id                 | 
| name               |     
| shift              | 
+--------------------+
+--------------------+
| InscribedStudent   | 
+--------------------+
| id                 | 
| student_id         | << Foreign key 
| clas-s-room_id       | << Foreign key 
+--------------------+
+--------------------+
| SelectionProcess   | 
+--------------------+
| id                 | 
| clas-s-room_id       | << Foreign key
| enabled            |
+--------------------+
+-------------------------+
| StudentSelectionProcess | 
+-------------------------+
| id                      | 
| inscribed_student_id    | << Foreign key
| selection_process_id    | << Foreign key
| status                  |
+-------------------------+

我的查询生成器

$student = DB::table('students')
            ->join('inscribed_students', 'inscribed_students.student_id', '=', 'students.id')
            ->join('clas-s-rooms', 'clas-s-rooms.id', '=', 'inscribed_students.clas-s-room_id')
            ->join('selection_processes', 'selection_processes.clas-s-room_id', '=', 'clas-s-rooms.id')
            // If exists show, else null
            ->leftjoin('student_selection_processes', 'student_selection_processes.selection_process_id', '=', 'selection_processes.id')
            ->select('students.*', 'clas-s-rooms.*', 'student_selection_processes.*')
            ->where([
                ['selection_processes.enabled', 1], // Very important
                ['students.id', $id]
            ])
            ->first();

但我认为这种方式非常混乱,仍然需要重新排列资源,所以我想知道是否可以将这个 Query 转换为 Eloquent 关系。。 p>

我预期的雄辩的 json 结果


  "id": 1,
  "name": "This is a Student",
  "email": "dborer@example.org",
  "enrolled": [
    
      "id": 31,
      "name": "This is a Clas-s-room",
      "shift": "Morning",
      "process: 
        "id": 5,
        "status": "Approved"   
       
    
  ]

我可以去教室,但我不知道如何获得流程

// StudentController.php - Student controller
$student = Student::with(['enrolled'])
           ->find($id);

// Student.php - Student Model
public function enrolled()

    return $this->belongsToMany('App\Clas-s-room', 'inscribed_students');

如果可能,如果 student_selection_processes 为 null,则不显示相关教室

【问题讨论】:

你能展示你的模型和数据库设计吗? @DilipHirapara 我更新了模型结构 【参考方案1】:

我不完全了解您的需求,但是,这样的事情可能会有所帮助:

Student::with(['clas-s-room', 'clas-s-room.selectionProcess', 'clas-s-room.selectionProcess.StudentSelectionProcess'])
    ->having(['clas-s-room.selectionProcess.StudentSelectionProcess'])
    ->find($id);

查看 Laravel 文档中的嵌套预加载:https://laravel.com/docs/5.8/eloquent-relationships#eager-loading

【讨论】:

【参考方案2】:

模型学生(表名)

//relation beetween student and clas-s-room
public function StudentClas-s-room()
    return $this->belongsToMany('App\Clas-s-room','inscribed_student','student_id','clas-s-room_id')->withTimestamps();


//relation beetween Student and InscribedStudent   
public function enrolled()
    return $this->hasMany('App\InscribedStudent','student_id','id');

模型教室(表名)

//relation beetween clas-s-room and student
public function clas-s-roomstudents()
    return $this->belongsToMany('App\Student','inscribed_student','clas-s-room_id','student_id')->withTimestamps();



//relation beetween clas-s-room and SelectionProcess
public function selectionclass()
    return $this->hasMany('App\SelectionProcess','clas-s-room_id','id');

模型SelectionProcess(表名)

 //relation beetween SelectionProcess and InscribedStudent
public function SelectionProcesInscribedStudent()
    return $this->belongsToMany('App\InscribedStudent','student_selection_process ','inscribed_student_id','selection_process_id')->withTimestamps();

模型InscribedStudent(表名)

 //relation beetween InscribedStudent and SelectionProcess
public function InscribedStudentSelectionProces()
    return $this->belongsToMany('App\SelectionProcess','student_selection_process ','selection_process_id','inscribed_student_id')->withTimestamps();


//relation beetween InscribedStudent and Student
public function student()

    return $this->belongsTo('App\Student','student_id','id');


//relation beetween InscribedStudent and clas-s-room
public function clas-s-room()

    return $this->belongsTo('App\clas-s-room','clas-s-room_id','id');

模型StudentSelectionProcess(表名)

//relation beetween StudentSelectionProcess and InscribedStudent
public function inscribed_student()

    return $this->belongsTo('App\InscribedStudent','inscribed_student_id','id');


//relation beetween StudentSelectionProcess and SelectionProcess
public function selection_process()

    return $this->belongsTo('App\SelectionProcess','selection_process_id','id');

现在在你的控制器中做

Student::with(['StudentClas-s-room','enrolled.InscribedStudentSelectionProces']);

【讨论】:

【参考方案3】:

看看这个:https://laravel.com/docs/5.8/eloquent-relationships

我就是这样做的。将关系重命名为您将在模型中创建的关系。

$student = Student::with(['manyToMany_clas-s-rooms_students.hasMany_selectionProcess' => function($query1) use($id) 
    $query1->where('enabled', 1);
    $query1->with(['hasMany_studentSelectionProcess' => function($query2) use($id) 
        $query2->where('student_id', $id);
    ])
])->find($id);

我也会为此改变你的桌子

+--------------------+
| InscribedStudent   | 
+--------------------+
| //id               | << Remove id -> you don't need this for that situation
| student_id         |
| clas-s-room_id       |
+--------------------+

+-------------------------+
| StudentSelectionProcess | 
+-------------------------+
| id                      |
| student_id              | << Refer directly to your student -> InscribedStudent is 
| selection_process_id    |           not a model, it's a pivot table
| status                  |
+-------------------------+

使用它,通过正确的关系,您可以找到具有 StudentSelectionProcess 的用户。加入选拔过程,然后加入课堂。

Student -> hasMany -> StudentSelectionProcess -> belongsTo -> SelectionProcess -> belongsTo -> Clas-s-room

花时间正确地建立关系会让你的生活更轻松。

【讨论】:

所有表至少有5个字段,我只是总结了解决我的问题的重要内容。进行此更改将无法解决此项目的目的 那不要改了,把student_id加到你的StudentSelectionProcess中? 我的 StudentSelectionProcess 有一个 InscribedStudent,而 InscribedStudent 有 Student,所以如果我添加 student_id 将出现一个保留 cicle Yes 和 No,它将让您直接使用 Student 模型从 StudentSelectionProcess 表中查询数据,而不是通过其他模型。如果您想向学生显示 StudentSelectionProcess 的每个状态,您可以使用 $student = Student::with('hasMany_studentSelectionProcess ')-&gt;find($id); 获取它们

以上是关于Laravel 查询构建器与雄辩的关系的主要内容,如果未能解决你的问题,请参考以下文章

Laravel 雄辩与查询构建器的优缺点

雄辩的查询构建器laravel 5.6中的未知列

Laravel 查询构建器与 where 左外连接

laravel 雄辩的查询构建器更新自定义时间戳字段而没有任何逻辑

查询生成器的行为就像雄辩

laravel 查询构建器计数关系