讲解例子:
用户表 ( user )结构:
id | 索引 |
username | 用户名 |
department_id | 关联部门表ID |
部门表 ( department )结构:
id | 索引 |
name | 部门名称 |
branch_id | 关联公司表ID |
[1. 单表查询]
user 表的 index 控制器
public function actionIndex(){
$params = \Yii::$app->request->getQueryParams();
$query = User::find();
$res = $query->all();
return $res;
}
可以获取 user 表的所有数据行构成的数组:
res => [
0:{ id: 1, username: '用户1', department_id: 1 },
1:{ id: 2, username: '用户2', department_id: 2 },
2:{ id: 3, username: '用户3', department_id: 3 }
]
[2. 两表关联查询]
在 user 表的 模型文件 user.php 中加入与department的关联关系
// 建立新字段来获取关联用户的信息
public function extraFields() {
$fields = [
// 获取关联部门的信息
'department' => function ($model) {
return $model->department;
},
]
}
// 建立用户表的department_id 与 部门表的id 的关联关系
public function getDepartment() {
return $this->hasOne(Department::class, ['id' => 'department_id']);
}
然后现在再调用 user表的index控制器时,传入 expand 参数. expand: 'department'
可以获取User表的所有数据行构成的数组,同时每个数据行对象中还会包含department子对象如下:
res => [
0:{
id: 1,
username: '用户1',
department_id: 1,
department: {
id: 1,
name: '公安部',
branch_id: 1
}
},
1:{ ... },
2:{ ... }
]
[3. 三表关联查询]
简单的两表查询,实现了通过查询用户表直接获得部门表某个部门的名称.
那么现在我将建立一个新表: 公司表 branch
id | 索引 |
name | 公司名称 |
现在需要查询用户表的时候,获取到用户的部门,并通过其部门的公司ID获取到其公司,然后得到公司名称
在 user 表的 模型文件 user.php 中已经有了 用户表 与 部门表的关联关系: department
因此现在需要创建一个用户表到公司部的新的关联关系: branch
// 将 department 关联关系 作为中间关系 , 通过 via() 方法实现关联
public function getBranch() {
return $this->hasOne(Branch::class, ['id' => 'branch_id'])->via('department')
}
// 然后建立一个新的字段用来装载关联公司信息:
public function extraFields() {
$fields = [
// 获取关联部门的信息
'department' => function ($model) {
return $model->department;
},
// 获取关联公司的信息
'branch' => function ($model) {
return $model->branch;
},
]
}
然后现在再调用 user表的index控制器时,传入 expand 参数. expand: 'department,branch'
可以获取User表的所有数据行构成的数组,同时每个数据行对象中还会包含department和branch子对象如下:
res => [
0:{
id: 1,
username: '用户1',
department_id: 1,
department: {
id: 1,
name: '综合部',
branch_id: 1
},
branch: {
id: 1,
name: '华建电力公司'
}
},
1:{ ... },
2:{ ... }
]
// 然后通过res[0].branch.name就可以获取分公司名称了
[四表及N表关联的查询]
根据三表的方法,可以得出以下结论:
例如 要实现四层链表列表数组的获取(A->B->C->D, A 要获取 D 的内容) , 需要先建立三层链表的关联关系. 将此关联关系作为中间关系, 通过via()方法来实现关联.
因此要建立三层链表的关联关系(A->B->C, A 要获取 C 的内容), 需要先建立两层链表的关联关系(A->B, A 要获取 B 的内容), 将两层链表的关联关系作为中间关系, 通过via()方法来实现关联.
因此无论是A->N的多少层链表关系, 只需要逐级建立关联关系, 然后在查询参数中传入expand=关联关系名 ,即可在查询结果数组里获取到该内容了.
---------------------- 分割线 ----------------------
上面讲的是通过index方法获取列表时的关联查询, 而不是筛选查询, 筛选查询是指传入参数 ( 查询某个字段为什么值 )
筛选查询如何实现多表筛选查询呢?
-
1. 筛选部门名称为'综合部'的所有用户. 就是简单的两表关联筛选.
-
2. 筛选公司名称为'华建电力公司'的所有用户, 就是三表关联筛选.
// 1.默认的用户表的index控制器:
public function actionIndex(){
$params = \Yii::$app->request->getQueryParams();
$query = User::find();
$res = $query->all();
return $res;
}
// 2. 加入查询判断实现两表关联查询:
public function actionIndex(){
$params = \Yii::$app->request->getQueryParams();
$query = User::find();
// 当传入的参数包含department_name表示通过部门名筛选查询
if(isset($params['department_name'])) {
// 通过leftJoin建立用户表与部门表的关联关系
$query->leftJoin('department', 'user.department_id = department.id');
// 然后就可以直接通过部门表的name字段来筛选了
$query->andWhere(['department.name'=> $params['department_name']]);
}
$res = $query->all();
return $res;
}
// 3. 实现三表关联查询:
public function actionIndex(){
$params = \Yii::$app->request->getQueryParams();
$query = User::find();
// 当传入的参数包含department_name表示通过部门名筛选查询
if(isset($params['branch_name'])) {
// 通过leftJoin建立用户表与部门表的关联关系
$query->leftJoin('department', 'user.department_id = department.id');
// 通过leftJoin建立部门表与公司表的关联关系
$query->leftJoin('branch', 'department.branch_id =branch.id');
// 然后就可以直接通过公司表的name字段来筛选了
$query->andWhere(['branch.name'=> $params['branch_name']]);
}
$res = $query->all();
return $res;
}
// 4. 实现N表关联查询: 就是根据层次使用leftJoin从当前表往目标表建立关联关系