一對多模型關(guān)聯(lián)
1.前言
前面小節(jié)介紹了如何在課程列表中使用一對一模型關(guān)聯(lián)出教師信息,本小節(jié)介紹如何在學(xué)生課程關(guān)聯(lián)列表中一對多關(guān)聯(lián)出學(xué)生選課信息,一對多模型關(guān)聯(lián)主要針對的是查詢兩個表有一對多的關(guān)系,而連表查詢就可能帶來性能問題, ThinkPHP
中提供了 with()
方法用于這種連表查詢的預(yù)加載,在一對多模型關(guān)聯(lián)的時候,框架底層會用過主驅(qū)動表的 id
集去另外一張表中 IN
查詢一次獲取全部數(shù)據(jù)并且能自動對應(yīng),這樣的操作就減少了開發(fā)者書寫很多循環(huán)和處理數(shù)據(jù)的代碼了。
2.添加測試數(shù)據(jù)
這里為了演示方便,需要向之前新建好的 學(xué)生表(student)
、學(xué)生課程關(guān)聯(lián)表(student_course)
添加數(shù)據(jù),添加學(xué)生表數(shù)據(jù)的 SQL
如下:
如下圖所示:
添加學(xué)生課程關(guān)聯(lián)表數(shù)據(jù) SQL
語句如下:
如下圖所示:
3.定義路由
這里復(fù)用上小節(jié)的控制器,只需要定義一個學(xué)生課表關(guān)列表的路由:
//學(xué)生課程表關(guān)聯(lián)列表接口
Route::get('course-students','app\controller\Study\CourseController@courseStudnetList');
如下圖所示:
4.方法定義
/**
* 學(xué)生課表信息關(guān)聯(lián)表
* @return \think\response\Json
*/
public function courseStudnetList(){
//每頁條數(shù)
$size = (int)$this->request->param('size', 15);
$courseStudents = StudentModel::order('created_at DESC')
->with('course_students')
->paginate($size);
return json($courseStudents);
}
如下圖所示:
5.設(shè)置一對多模型關(guān)聯(lián)方法
在 StudentModel
中可以定義 courseStudents
方法:
/**
* 一對多模型關(guān)聯(lián)
* @return \think\model\relation\HasMany
*/
public function courseStudents(){
return $this->hasMany(StudentCourseModel::class,"student_id","id");
}
如下圖所示:
6.請求模型關(guān)聯(lián)之后的數(shù)據(jù)
下面使用 postman
請求接口數(shù)據(jù)如下:
{
"total": 14,
"per_page": 10,
"current_page": 1,
"last_page": 2,
"data": [
{
"id": 1,
"name": "趙雷",
"age": 24,
"id_number": "42011720100506XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 1,
"student_id": 1,
"course_id": 1,
"created_at": 1603617951
},
{
"id": 2,
"student_id": 1,
"course_id": 2,
"created_at": 1603617951
},
{
"id": 3,
"student_id": 1,
"course_id": 2,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 2,
"name": "孫空",
"age": 23,
"id_number": "42011720110606XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 4,
"student_id": 2,
"course_id": 3,
"created_at": 1603617951
},
{
"id": 5,
"student_id": 2,
"course_id": 4,
"created_at": 1603617951
},
{
"id": 6,
"student_id": 2,
"course_id": 6,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 3,
"name": "錢學(xué)",
"age": 18,
"id_number": "42011720120306XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 7,
"student_id": 3,
"course_id": 4,
"created_at": 1603617951
},
{
"id": 8,
"student_id": 3,
"course_id": 1,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 4,
"name": "王五",
"age": 25,
"id_number": "42011720030506XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 9,
"student_id": 4,
"course_id": 1,
"created_at": 1603617951
},
{
"id": 10,
"student_id": 4,
"course_id": 3,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 5,
"name": "張紅",
"age": 19,
"id_number": "42011720050506XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 11,
"student_id": 5,
"course_id": 5,
"created_at": 1603617951
},
{
"id": 12,
"student_id": 5,
"course_id": 6,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 6,
"name": "吳曉明",
"age": 21,
"id_number": "42011720040506XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 13,
"student_id": 6,
"course_id": 4,
"created_at": 1603617951
},
{
"id": 14,
"student_id": 6,
"course_id": 2,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 7,
"name": "李珍",
"age": 25,
"id_number": "42011720060206XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [
{
"id": 15,
"student_id": 7,
"course_id": 3,
"created_at": 1603617951
},
{
"id": 16,
"student_id": 7,
"course_id": 4,
"created_at": 1603617951
}
],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 8,
"name": "豬剛",
"age": 22,
"id_number": "42011720070806XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 9,
"name": "李亮",
"age": 26,
"id_number": "42011720080906XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [],
"created_at_text": "2020-10-25 17:25"
},
{
"id": 10,
"name": "周康",
"age": 28,
"id_number": "42011720000706XXXX",
"created_at": 1603617951,
"update_at": 0,
"status": 1,
"course_students": [],
"created_at_text": "2020-10-25 17:25"
}
]
}
如下圖所示:
7.小結(jié)
本小節(jié)主要介紹了一對多模型關(guān)聯(lián),其中使用 with
預(yù)加載底層實現(xiàn)是 IN
查詢一次性查出來的,所以無需擔(dān)心存在循環(huán)查詢的問題,另外如需要在上述結(jié)果中繼續(xù)關(guān)聯(lián)出課程信息可以如下使用 with
閉包查詢:
/**
* 學(xué)生課表信息關(guān)聯(lián)表
* @return \think\response\Json
*/
public function courseStudnetList(){
//每頁條數(shù)
$size = (int)$this->request->param('size', 15);
$courseStudents = StudentModel::order('created_at DESC')
->with(['course_students' => function($query){
$query->with('course');
}])
->paginate($size);
return json($courseStudents);
}
其中需要在 CourseStudentModel
模型中新建 course
一對一關(guān)聯(lián)課程信息。
Tips: 代碼倉庫:https://gitee.com/love-for-poetry/tp6