[TOC]
# 使用joinWith实现左联接
用模型进行联表查询之前最好先给模型定义好模型关系,假设Article模型的`getUser`这个getter是通过hasOne返回文章的发表用户模型,则要一次性用join方法查出来是这样:
~~~php
//SELECT `article`.* FROM `article` LEFT JOIN `user` ON `article`.`user_id` = `user`.`id` WHERE `article`.`id`=1
$article = Article::find()
->where(['article.id' => 1])
->joinWith('user')
->orderBy(['user.id' => SORT_DESC])
->one();
echo $article->title;
echo $article->user->name; //不会产生查询,因为上面join的时候已经查过了,所以user模型已经生成
~~~
其中要注意where的条件要声明表名以区分条件字段,否则容易造成同名字段冲突
# 使用innerJoinWith实现内联接
查询所有文章以及作者
~~~php
//SELECT * FROM `article` INNER JOIN `user` ON `article`.`user_id` = `user`.`id` WHERE `article`.`id` IN (1,2,3)
$articles = Article::find()->innerJoinWith('user')->where(['in', 'article.id', [1, 2, 3]])->all();
foreach($articles as $article){
echo $article->user->name; //不会产生查询
}
~~~
# 指定表别名
~~~php
Article::find()->joinWith(['user u'])->orderBy(['u.id' => SORT_DESC])……
~~~
# 多表联接
~~~php
/*
SELECT * FROM article
LEFT JOIN user on article.user_id = user.id
LEFT JOIN article_type ON article.type_id = article_type.id ……
*/
Article::find()->joinWith(['user', 'articleType'])……
~~~
这样就会调用Article::getUser和Article::getArticleType两个方法来获取关系并构造联表了
联表方法本来是可以接收一个字符串作为快速联单表的,如果要联多表,就像上面这样写成数组,然后一个数组元素就是一个联表,你要联多少表就堆多少个元素吧![](http://www.kkh86.com/it/face/fengkuanggongji.gif)
# join的时候在on条件里追加更多条件
以上例子中都只是单纯地拿两个表的关系字段做on对等比较,如果有自己自定义需求可以用`onCondition`方法:
~~~php
//SELECT `article`.* FROM `article` LEFT JOIN `user` ON (`article`.`user_id` = `user`.`id`) AND (`user`.`status` = 1) WHERE `article`.`id`=1
$article = Article::find()
->where(['article.id' => 1])
->joinWith([
'user' => function($arQuery){
$arQuery->onCondition(['user.status' => 1]); //重点
}
])
->one();
echo $article->title;
echo $article->user->name; //不会产生查询,因为上面join的时候已经查过了,所以user模型已经生成
~~~
这个条件追加与[AR模型查询优化](http://www.kkh86.com/it/yii2/guide-db-ar-select.html)里面的**在with时追加其它条件**小节的做法是一样的,把joinWith或innerJoinWith里的参数换成数组,key是关联属性名称(对应的模型getter),value是一个回调,接收一个AR查询器,通过这个AR查询器用onCondition来追加条件
但不能用这样的链式查询来实现:`joinWith('user')->onCondition($condition)->all()`这是无效的代码
其中onCondition方法的条件声明和where是一样的
- 目录
- 配置
- 简介
- 别名
- gii
- 配置项
- 模型
- 简介
- 增删改查
- AR和model
- 模型事件
- 场景
- query查询
- 增删改
- AR查询器
- 模型关系定义
- AR模型连表查询
- fields
- where拼接
- 模块
- 创建模块
- 控制器
- 表单
- 跳转
- 响应
- 验证器
- Action
- 组件
- url
- 分页
- 验证码
- 缓存
- 文件上传
- 预启动组件
- 事件
- 自定义组件
- redis
- 日志
- 行为
- cookie和session
- 基础知识
- 创建一个类
- 配置一个类
- object基类
- component组件类特性
- phpstorm无法更改php等级
- url地址美化
- 过滤器
- 请求处理
- 请求组件
- 响应组件
- header
- 用户登录
- 实现IdentityInterface接口
- 登录
- 自动检测登录
- 获取用户信息
- 访问行为追踪
- phpstorm+postman断点调试