Yii2 ActiveRecord多表关联及多表关联搜索的实现


Posted in PHP onJune 30, 2016

Yii的ActiveRecord是与数据库打交道的类,也即MVC中的M(模型层),也是ORM的O(Object)。

一个老生常谈的问题。最近通过群里的反馈,觉得很多人还是没有去理解这个问题。今天把这个问题讲明白了,看看yii2 ActiveRecord是怎么个多表关联以及如何去优化这个关联。

场景需求:

假设我们有一张用户表user和一张用户渠道表auth,两张数据表通过user.id和auth.uid进行一对一关联。现需要在user列表展示auth表的来源渠道source,且该渠道可搜索。

首先我们先通过gii生成user和auth系列相关的model和操作。此处不做详细说明,有关gii的操作可参考xxx

我看继续看重要的几个操作步骤:

1、找到user表对应的AR模型类 common\models\User.php,在该类文件中进行关联auth表

/**
* 关联auth表
*/
public function getAuth()
{
// hasOne要求返回两个参数 第一个参数是关联表的类名 第二个参数是两张表的关联关系 
// 这里uid是auth表关联id, 关联user表的uid id是当前模型的主键id
return $this->hasOne(common\models\Auth::className(), ['uid' => 'id']);
}

设置好了之后,并不代表两张数据表自动进行关联了!我们访问user列表页(该列表页采用gii生成,目前我们没操作过),通过debug查看Database Queries不难发现,实际中的query并没有进行关联auth表

2、在gridview中添加关联表的来源渠道字段source

<?= GridView::widget([
// other codes
'columns' => [
// other columns
'auth.source',
]
]); ?>

有同学感觉疑问了,上面不是说了没进行关联吗,这个怎么可以直接使用auth.source?

先别急,此时我们打开debug看看实际的query。

我们会发现有很多类似 select * from `auth` where uid = xxx;之类的操作,如果你的分页默认20条数据时,会有20个类似的query。

我们先搞明白发生了什么?

实际上这属于php的基础知识了。读取和写入对象的一个不存在的成员变量时, __get() __set() 魔术函数会被自动调用。yii也是利用了这一点对其进行了实现!

该操作跟大部分人在gridview中封装方法获取关联表数据几乎一致,但是!20条sql的查询明显增加了众多的开销。如果这里是left join操作多好!

3、优化sql

我们需要优化的是:

20条sql变1条sql

只获取关联表需要的字段

有同学要嚷嚷了,这里是yii自带的操作,怎么优化?我们回到数据源的获取上,发现user列表的数据是通过userSearch model的search方法提供的。

也就是说我们的数据查询实际上就没有去进行关联表查询!既然如此,我们就在UserSearch加上关联查询

$query = User::find();
$query->joinWith(['auth']);
$query->select("user.*, auth.source");

我们再来刷新下user列表页,然后通过debug分析发现有两条sql引起了我们的注意

SELECT `user`.*, `auth`.`source` FROM `user` LEFT JOIN `auth` ON `user`.`id` = `auth`.`uid` LIMIT 20
SELECT * FROM `auth` WHERE `user_id` IN (20个uid);

也就是说我么已经达到了优化sql的目的,通过debug分析发现,DB的查询时间少了很多。

4、关联表字段增加查询

gridview中的搜索模型也是通过searchModel实现的,该模型通过rules控制着哪个字段可搜索,哪个字段不可搜索。

我们现在需要增加关联表的source可搜索,因此我们在searchModel中定义一个属性source且添加到rules中

public $source;
public function rules()
{
return [
// other rules
['source', 'safe'],
];
}

接着我们把gridview中的auth.source修改一下

// 'auth.source',
[
'attribute' => 'source',
'value' => 'auth.source',
'label' => '渠道来源',
],

到这里我们界面上是ok的,要实现程序上的搜索还差一步,我们在数据源获取的地方加上新增的source条件即可

$query->andFilterWhere([
// other params
'auth.source' => $this->source,
]);

下面给大家补充yii中ActiveRecord的一些用法

1,对象转数组

$model = new ActiveRecord();
$model.toArray();

由于ActiveRecord不是简单数组,不能直接json_encode,否则信息不完整。

解决办法:$model.toArray();这样就变为简单数组了,可以进行json_encode了。

2,通过名字或其他字段直接获取ActiveRecord的id。

$nIdcId = idc_info::model()->find('name like :name',array(':name'=>"%".$strIdcName."%"))->id;

我以前经常使用的办法是(现在发现很土):

$idc = Idc::model()->find("..."); 
$id = $idc->id;

3,对model的理解

$accModel = call_user_func(array(ActiveRecordName, 'model')); 
$model  = $accModel->findByPk($id);

以上所述是小编给大家介绍的Yii2 ActiveRecord多表关联及多表关联搜索的实现的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

PHP 相关文章推荐
PHP开启gzip页面压缩实例代码
Mar 11 PHP
第4章 数据处理-php字符串的处理-郑阿奇(续)
Jul 04 PHP
初学PHP的朋友 经常问的一些问题。不断更新
Aug 11 PHP
关于shopex同步ucenter的redirect问题,导致script不运行
Apr 10 PHP
CentOS 6.2使用yum安装LAMP以及phpMyadmin详解
Jun 17 PHP
destoon复制新模块的方法
Jun 21 PHP
php操作xml入门之xml基本介绍及xml标签元素
Jan 23 PHP
PHP输出九九乘法表代码实例
Mar 27 PHP
php基于PDO实现功能强大的MYSQL封装类实例
Feb 27 PHP
php实现有序数组旋转后寻找最小值方法
Sep 27 PHP
实例介绍PHP中zip_open()函数用法
Feb 15 PHP
php设计模式之职责链模式定义与用法经典示例
Sep 19 PHP
eclipse php wamp配置教程
Jun 30 #PHP
PHP上传图片类显示缩略图功能
Jun 30 #PHP
PHP使用php-resque库配合Redis实现MQ消息队列的教程
Jun 29 #PHP
Thinkphp批量更新数据的方法汇总
Jun 29 #PHP
ThinkPHP实现更新数据实例详解(demo)
Jun 29 #PHP
php结合mysql与mysqli扩展处理事务的方法
Jun 29 #PHP
php简单解析mysqli查询结果的方法(2种方法)
Jun 29 #PHP
You might like
Zend Framework教程之前端控制器Zend_Controller_Front用法详解
2016/03/07 PHP
jquery中html、val与text三者属性取值的联系与区别介绍
2013/12/29 Javascript
浅析jQuery中调用ajax方法时在不同浏览器中遇到的问题
2014/06/11 Javascript
两款JS脚本判断手机浏览器类型跳转WAP手机网站
2015/10/16 Javascript
js省市联动效果完整实例代码
2015/12/09 Javascript
JavaScript学习笔记之ES6数组方法
2016/03/25 Javascript
全面解析Bootstrap中tab(选项卡)的使用方法
2016/06/06 Javascript
AngularJS 入门教程之事件处理器详解
2016/08/19 Javascript
使用vue.js实现联动效果的示例代码
2017/01/10 Javascript
jQuery实现元素的插入
2017/02/27 Javascript
详解VueJs异步动态加载块
2017/03/09 Javascript
微信小程序 MD5的方法详解及实例代码
2017/03/10 Javascript
基于js中this和event 的区别(详解)
2017/10/24 Javascript
AngularJS模糊查询功能实现代码(过滤内容下拉菜单排序过滤敏感字符验证判断后添加表格信息)
2017/10/24 Javascript
Vue.js watch监视属性知识点总结
2019/11/11 Javascript
JavaScript多种滤镜算法实现代码实例
2019/12/10 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
2020/06/02 Javascript
vue+vuex+axios从后台获取数据存入vuex,组件之间共享数据操作
2020/07/31 Javascript
[02:12]Dota 2 推出全新英雄—— 电炎绝手
2019/08/23 DOTA
Python字符串详细介绍
2015/05/09 Python
python计算文本文件行数的方法
2015/07/06 Python
Python实现变量数值交换及判断数组是否含有某个元素的方法
2017/09/18 Python
不知道这5种下划线的含义,你就不算真的会Python!
2018/10/09 Python
pygame实现飞机大战
2020/03/11 Python
基于python tkinter的点名小程序功能的实例代码
2020/08/22 Python
Python读取pdf表格写入excel的方法
2021/01/22 Python
python如何用matplotlib创建三维图表
2021/01/26 Python
css3使用animation属性实现炫酷效果(推荐)
2020/02/04 HTML / CSS
电子商务网站的创业计划书
2014/01/05 职场文书
校园安全教育广播稿
2014/02/17 职场文书
遗体告别仪式主持词
2014/03/20 职场文书
排查整治工作方案
2014/06/09 职场文书
社会体育专业大学生职业生涯规划书
2014/09/17 职场文书
感恩的心主题班会
2015/08/12 职场文书
CSS3鼠标悬浮过渡缩放效果
2021/04/17 HTML / CSS
六种css3实现的边框过渡效果
2021/04/22 HTML / CSS