laravel 模型关联查询的 belongsToMany 与预加载
belongsToMany
a表:a_table
+------+--------+
| a_id | a_name |
+------+--------+
b表:b_table
+------+--------+
| b_id | b_name |
+------+--------+
中间表:a_b_table
+------+------+------+
| id | a_id | b_id |
+------+------+------+
在a表AModel
中的函数:
public function relateToB(){
return $this->belongsToMany("App\Models\BModel", "a_b_table", "a_id", "b_id");
}
belongsToMany
参数详解:
- 第一个参数:a表将要关联的b表模型。
- 第二个参数:中间表表名。
- 第三个参数:中间表的a表外键。即中间表关联a表所对应的键。
- 第四个参数:中间表的b表外键。即中间表关联b表所对应的键。
查询的结果相当于 inner join
,而非 left join
,同样belongsToMany
也会返回重复内容。
预加载
没有预加载的情况:
$all = AModel::all();
foreach($all as $single)
{
single->relateToB(); >> 注意:这里是在调用 relateToB() 函数。
}
- 先
find
获取一个Model
对象 ,即获取一个id=1
的行, - 再根据这个
Model
对象,调用relateToB()
,来获取中间表中a_id=1
对应的b_id
所对应的 b表 中的行,获取的结果是一个Illuminate\Database\Eloquent\Collection
对象。Illuminate\Database\Eloquent\Collection
对象:
1、既可以充当数组使用,比如var c = new \Collection;
c[0];
2、又可以充当查询构造器使用,比如var c = new \Collection;
c->all();
c->where();
3、该数组对象的元素类型为BModel
。
4、该数组对象的元素类型BModel
的内容不仅包含BModel
的全部字段键值对,还包括了一个pivot
的键,对应的值是一个Illuminate\Database\Eloquent\Relations\Pivot
类型对象,该对象默认只能包含存在于中间表的键值对。
单次 `single->relateToB();` 返回结果:
=> Illuminate\Database\Eloquent\Collection {#4388
all: [
App\Models\BModel {#4403
b_id:1
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4397
a_id: 1,
b_id: 4,
created_at: null,
updated_at: null,
},
},
App\Models\BModel {#4400
b_id: 1,
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4378
a_id: 1,
b_id: 5,
created_at: null,
updated_at: null,
},
},
],
}
总结:
1、先从数据库中的把 a表
全部数据查询出来,再对查询结果挨个进行 relateToB
查询,
2、而 relateToB
查询 是【根据 a表
的结果】,从【数据库的中间表中】分析出数据库中【对应的b表
】。
3、也就是向从数据库查询a表
后,又要从数据库中循环的查询b表
。
select * from `posts`
select * from `authors` where `authors`.`id` = ? limit 1 [1]
select * from `authors` where `authors`.`id` = ? limit 1 [1]
select * from `authors` where `authors`.`id` = ? limit 1 [1]
有预加载的情况
$all = AModel::with("relateToB")->get();
foreach($all as $single)
{
single->relateToB; >> 注意:这里是获取键对应的值,并非是函数调用。
}
AModel::with("relateToB")->get() 查询的结果:
=> Illuminate\Database\Eloquent\Collection {#4332
all: [
App\Models\AModel {#4334
a_id: 1,
created_at: null,
updated_at: null,
relateToB: Illuminate\Database\Eloquent\Collection {#4350
all: [
App\Models\BModel {#4362
b_id: 91,
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4356
a_id: 1,
b_id: 91,
created_at: null,
updated_at: null,
},
},
App\Models\BModel {#4368
b_id: 92,
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4348
a_id: 1,
b_id: 92,
created_at: null,
updated_at: null,
},
},
],
},
},
App\Models\AModel {#4337
a_id: 2,
created_at: null,
updated_at: null,
relateToB: Illuminate\Database\Eloquent\Collection {#4333
all: [],
},
},
App\Models\AModel {#4338
a_id: 3,
created_at: null,
updated_at: null,
relateToB: Illuminate\Database\Eloquent\Collection {#4175
all: [
App\Models\BModel {#4364
b_id: 94,
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4352
a_id: 3,
b_id: 94,
created_at: null,
updated_at: null,
},
},
App\Models\BModel {#4366
b_id: 96,
created_at: null,
updated_at: null,
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4346
a_id: 3,
b_id: 96,
created_at: null,
updated_at: null,
},
},
],
},
},
],
}
总结:
1、先从数据库中的把 a表
全部数据查询出来,而该查询结果直接就包含了对应关联的 b表
内容。
2、再从查询结果中直接获取 relateToB
的值
3、也就是向从数据库查询a表
后,直接从查询结果继续查询,并不会再向数据库中查询关联表。
select * from `posts`
select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?)
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: