一对一模型关联

1. 前言

本小节介绍如何使用模型关联,当你需要使用多表联合查询数据的时候,若使用模型关联可以让代码变得更简洁,一对一模型关联主要针对的是两个表中的数据只有一对一的关系,或者只需要取出一对一关系的数据。

2. 添加测试数据

这里为了演示方便,需要向之前新建好的 课程表(course)教师表(teacher) 添加数据,添加教师表数据 SQL 如下:
图片描述
如下图所示:
图片描述
添加课程表数据 SQL 语句如下:
图片描述
如下图所示:
图片描述

3. 接口路由定义

这里以查询课程表(course) 数据为例,通过一对一模型关联出课程表对应的教师信息:

Route::get('courses','app\controller\Study\CourseController@courseList');

如下图所示:
图片描述

4. 控制器和方法定义

下面贴出路由中定义的控制器和查询方法:

<?php
namespace app\controller\Study;
use app\BaseController;
use app\Models\Study\CourseModel;
class CourseController extends BaseController
{
    /**
     * 获取教师列表
     */
    public function courseList()
    {
        $size = (int)$this->request->param('size', 15);
        $students = CourseModel::where('status', 1)->order('created_at DESC')->paginate($size);
        return json($students);
    }
}

如下图所示:
图片描述

5. 请求课程列表接口数据

下面使用 postman 请求接口数据如下:

{
    "total": 6,
    "per_page": 10,
    "current_page": 1,
    "last_page": 1,
    "data": [
        {
            "id": 1,
            "course_name": "广义相对论",
            "teacher_id": 1,
            "created_at": 1603617951,
            "update_at": 0,
            "status": 1
        },
        {
            "id": 2,
            "course_name": "电动力学",
            "teacher_id": 2,
            "created_at": 1603617951,
            "update_at": 0,
            "status": 1
        },
        {
            "id": 3,
            "course_name": "电磁学",
            "teacher_id": 3,
            "created_at": 1603617951,
            "update_at": 0,
            "status": 1
        },
        {
            "id": 4,
            "course_name": "光学",
            "teacher_id": 4,
            "created_at": 1603617951,
            "update_at": 0,
            "status": 1
        },
        {
            "id": 5,
            "course_name": "信息论",
            "teacher_id": 5,
            "created_at": 1603617951,
            "update_at": 0,
            "status": 1
        },
        {
            "id": 6,
            "course_name": "天文学",
            "teacher_id": 6,
            "created_at": 1603617951,
            "update_at": 0,
            "status": 1
        }
    ]
}

如下图所示:
图片描述

6. 设置模型关联方法

若要在课程列表数据中关联出教师信息可以在 CourseModel 模型中使用如下 teacher 方法:

<?php
namespace app\Models\Study;
use think\Model;
class CourseModel extends Model
{
    protected $table = 'course';

    /**
     * 一对一模型关联
     */
    public function teacher()
    {
        return $this->hasOne(TeacherModel::class, "id", "teacher_id");
    }
}

如下图所示:
图片描述

7. 使用 with 预加载出关联信息

可以在课程列表接口的方法中使用 with() 方法预加载出关联信息:

 $students = CourseModel::where('status', 1)
     ->with('teacher')
     ->order('created_at DESC')
     ->paginate($size);

Tips: 其中 with('teacher') 预加载出 teacher 属性,也可以不使用 with 被动加载出 teacher ,如调用 $studentModel->teacher 的时候,若模型不存在 teacher 属性,会触发模型关联同名的方法。

8. 请求模型关联之后的数据

下面使用 postman 请求接口部分数据如下:

{
     "id": 1,
     "course_name": "广义相对论",
     "teacher_id": 1,
     "created_at": 1603617951,
     "update_at": 0,
     "status": 1,
     "teacher": {
         "id": 1,
         "name": "爱老师",
         "age": 24,
         "id_number": "52011720100506XXXX",
         "created_at": 1603617951,
         "update_at": 0,
         "status": 1
     }
 }

Tips: 此时列表中出现了 teacher 属性字段,这个字段就是课程列表一对一关联出来的教师信息。

9. 小结

本小节主要介绍如何使用模型关联一对一的方式,在查询课程列表的时候关联出教师信息,这样就不必书写繁琐的连表查询逻辑。

需要注意的是,一般情况下使用模型关联最好使用 with 预加载出来,预加载列表信息底层实际使用的是 IN 查询一次全部查出列表内容,若在列表中被动触发可能会造成多次查询带来的性能问题。

Tips: 代码仓库:https://gitee.com/love-for-poetry/tp6