ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 一. Laravel 对象关联关系 ## 1. 对象与数据库表的关联 Laravel有一个强大的数据库工具ORM Eloquent,是每张数据表对应一个Model,对Model的操作就对应数据库的操作,你只用管对model的操作,SQL语句则根据对象模型操作自动生成。 之前写过一篇相关基础介绍的文章:链接: Laravel model 模型用法和部分问题解方法 ## 2. 对象(表)之间的关联关系 在我们代码编写过程中,对象之间有着多种的关联关系; 一对一 例如:学生有唯一对应的班级 一对多 例如:班级有很多个学生 相应的在我们的表中对应的表现就是外键,通过外键与主键相等的方式,进行关系的建立,那么在Laravel中如何进行关联查询呢? # 二. 对象关系映射关联关系的建立 ## 1. Model配置关联关系 我们想要在后续的查询中方便进行关联查询,首先我们要在Model中配置相关的关联关系: //name是关联关系的名称,通常我们使用表名代替,方便记忆 ``` public function name() { //返回我们的关系,使用不同的方法进行关系建立 return $this->belongsTo('关联对象', '关联外键', '关联主键'); } ``` ## 2. 关联关系种类方法 我们这里以班级class,负责人principal,学生student作为参考。 ### hasOne 班级有一个负责人,那就在班级对象中,新增负责人关联 ``` public function Principal(): \Illuminate\Database\Eloquent\Relations\BelongsTo { //hasOne( related:关联的对象模型 , foreignKey:'关联字段名') return $this->hasOne(Principal::class, 'class_id'); } ``` ### hasMany 一个班级有很多个学生,也就是一对多的关系,新增关联 ``` public function student(): \Illuminate\Database\Eloquent\Relations\BelongsTo { //hasOne( related:关联的对象模型 , foreignKey:'关联字段名') return $this->hasMany(Student::class, 'class_id'); } ``` ### belongsTo 负责人负责一个班级,那就在负责人对象中,可以新增班级关联 ``` public function class(): \Illuminate\Database\Eloquent\Relations\BelongsTo { //belongsTo( related:关联的对象模型 , foreignKey:'关联字段名')->->withDefault(); return $this->belongsTo(Class::class, 'principal_id')->withDefault(); } ``` ### withDefault: 正常情况下 负责人对应的班级是存在的,如果班级表中的数据删除,那么关联模型就会返回一个null值,避免所属父级被删除导致的异常问题 就是为了解决返回null所带来问题的。 ### belongsToMany 但是假设学生可以报多个班级,那么学生和班级的关系就会变成多对多的关系,我们通常会使用一个中间的关系表,进行关联 ``` public function class() { return $this->belongsToMany('目标对象','中间表','本表在中间表外键','目标表在中间表中外键','第三个参数如果对应的不是本表的主键则需要填写,反之不需要'); } ``` ``` hasOneThrough ``` 远程关联一对一,比方说一个用户拥有一个账本,账本中存在很多条消费记录,我想从消费记录中获取到该用户的信息,就需要远程一对一 ``` public function record() { return $this->hasOneThrough('目标对象','中间表','本表在中间表外键','目标表在中间表中外键','第三个参数如果对应的不是本表的主键则需要填写,反之不需要'); } ``` ### hasManyThrough ``` public function record() { return $this->hasManyThrough('目标对象名称','中间表','本表在中间表外键','目标表在中间表中外键','当前表与中间表关联字段名称','中间表和目标表关联的字段名称'); } ``` # 三. 对象关系映射关联关系的几种方法 ## 1. with 介绍 with 是一种渴求式预加载,with 更像 sql 中的 join,无论关联的结果中有没有值都会返回,如果没有就会返回一个空 使用方法 //with 中第一个参数就是我们上面建立关系的方法名 $query = Model::with('关系名称')->get(); 1 2 我们如果想要在进行关联查询时,对其进行筛选,我们也可以在with中写方法: //查询所有的用户,查询条件:发布过标题中有first的post ``` $query = Model::with([ '关系名称' => function ($query) { //对关联表进行筛选,可以用where,orWhere 等 $query->where('title', 'like', '%first%'); } ])->get(); ``` 如果我们想要携带参数: //查询所有的用户,查询条件:发布过标题中有first的post ``` $query = Model::with([ '关系名称' => function ($query) use ($searchWord) { //对关联表进行筛选,可以用where,orWhere 等 $query ->where('title', 'like', '%'.$searchWord.'%'); } ])->get(); ``` ## 2. whereHas 介绍 whereHas只会返回有结果的值,就可以有效避免with中出现空的返回值的情况 使用方法 基础用法与with相似 ``` $query = Model::whereHas('关系名称', function ($query) { $query->where('title', 'like', '%first%'); })->get(); ``` 但是whereHas可以嵌套 ``` $query = TeacherModel::query()->whereHas( 'merchant' , function ($query){ $query->whereHas( 'groups',function($query){ $query->where("查询字段","目标值"); } ); } )->where('name','like','%'.$searchWord.'%')->get(['id','name']); ```