亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

一對多模型關聯

1.前言

前面小節介紹了如何在課程列表中使用一對一模型關聯出教師信息,本小節介紹如何在學生課程關聯列表中一對多關聯出學生選課信息,一對多模型關聯主要針對的是查詢兩個表有一對多的關系,而連表查詢就可能帶來性能問題, ThinkPHP中提供了 with()方法用于這種連表查詢的預加載,在一對多模型關聯的時候,框架底層會用過主驅動表的 id 集去另外一張表中 IN 查詢一次獲取全部數據并且能自動對應,這樣的操作就減少了開發者書寫很多循環和處理數據的代碼了。

2.添加測試數據

這里為了演示方便,需要向之前新建好的 學生表(student)、學生課程關聯表(student_course) 添加數據,添加學生表數據的 SQL 如下:
圖片描述
如下圖所示:
圖片描述
添加學生課程關聯表數據 SQL 語句如下:
圖片描述
如下圖所示:
圖片描述

3.定義路由

這里復用上小節的控制器,只需要定義一個學生課表關列表的路由:

//學生課程表關聯列表接口
Route::get('course-students','app\controller\Study\CourseController@courseStudnetList');

如下圖所示:
圖片描述

4.方法定義

    /**
     * 學生課表信息關聯表
     * @return \think\response\Json
     */
    public function courseStudnetList(){
        //每頁條數
        $size = (int)$this->request->param('size', 15);

        $courseStudents = StudentModel::order('created_at DESC')
            ->with('course_students')
            ->paginate($size);

        return json($courseStudents);
    }

如下圖所示:
圖片描述

5.設置一對多模型關聯方法

StudentModel 中可以定義 courseStudents 方法:

    /**
     * 一對多模型關聯
     * @return \think\model\relation\HasMany
     */
    public function courseStudents(){
        return $this->hasMany(StudentCourseModel::class,"student_id","id");
    }

如下圖所示:
圖片描述

6.請求模型關聯之后的數據

下面使用 postman 請求接口數據如下:

{
    "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": "錢學",
            "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.小結

本小節主要介紹了一對多模型關聯,其中使用 with 預加載底層實現是 IN 查詢一次性查出來的,所以無需擔心存在循環查詢的問題,另外如需要在上述結果中繼續關聯出課程信息可以如下使用 with 閉包查詢:

    /**
     * 學生課表信息關聯表
     * @return \think\response\Json
     */
    public function courseStudnetList(){
        //每頁條數
        $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 一對一關聯課程信息。

Tips: 代碼倉庫:https://gitee.com/love-for-poetry/tp6