讲解例子:
用户表 ( 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从当前表往目标表建立关联关系