Yii2.0表关联查询实例分析


Posted in PHP onJuly 18, 2016

本文实例讲述了Yii2.0表关联查询的方法。分享给大家供大家参考,具体如下:

你可以使用 ActiveRecord 来进行关联查询(比如,从A表读取数据时把关联的B表数据也一起读出来), 在Active Record中,获取关联数据可以像访问主表ActiveRecord对象的属性(property)一样简单。

比如,通过合适的关系声明,你可以使用 $customer->orders 来获取一个 Order 对象数组,代表该客户下的订单。

要声明一个关系(relation),定义一个getter方法,该方法返回一个 yii\db\ActiveQuery 对象,拥有关联上下文信息,这样将只查询符合条件的相关数据。比如:

class Customer extends \yii\db\ActiveRecord
{
 public function getOrders()
 {
  // Customer has_many Order via Order.customer_id -> id
  return $this->hasMany(Order::className(), ['customer_id' => 'id']);
 }
}
class Order extends \yii\db\ActiveRecord
{
 // Order has_one Customer via Customer.id -> customer_id
 public function getCustomer()
 {
  return $this->hasOne(Customer::className(), ['id' => 'customer_id']);
 }
}

上述代码中的 yii\db\ActiveRecord::hasMany() 和 yii\db\ActiveRecord::hasOne() 是用来建模关系型数据库中的 一对多 以及 一对一 关联关系。比如,一个客户customer有多个订单orders,而一个订单拥有或归属于一个用户。两个方法均接收两个参数并返回一个 yii\db\ActiveQuery 对象:

$class: 关联模型的类名称。

$link: 两张表之间的列关联。这得是一个数组。数组元素的键是 $class 所对应表的列名称,而数组元素的值是当前声明类的列名称。依据表外键关联来定义这些关系是一个好的编程实践。

完成上述声明后,就可以通过定义相应的getter方法来像访问对象属性一样获取关联数据:

// get the orders of a customer
$customer = Customer::findOne(1);
$orders = $customer->orders; // $orders is an array of Order objects

上述代码在幕后实际执行了如下两个SQL查询,分别对应于上述两行代码:

SELECT * FROM customer WHERE id=1;
SELECT * FROM order WHERE customer_id=1;

提示:如果你再次访问 $customer->orders ,并不会重复执行上述第2行SQL查询。这条查询语句只在表达式第一次被访问时才被执行。后续的访问将直接返回内部缓冲数据。如果你想重新执行查询,只需要先调用一下unset来清除缓存:

unset($customer->orders);.

有时候,你可能想传递参数给关联查询来限定查询条件。比如只想读取超过指定数额的大额订单,而不是所有订单。为此,可以使用如下getter方法来声明一个 bigOrders 关系:

class Customer extends \yii\db\ActiveRecord
{
 public function getBigOrders($threshold = 100)
 {
  return $this->hasMany(Order::className(), ['customer_id' => 'id'])
   ->where('subtotal > :threshold', [':threshold' => $threshold])
   ->orderBy('id');
 }
}

记住 hasMany() 返回对象是一个 yii\db\ActiveQuery ,因此ActiveQuery的方法都可以被用来定制这个关联查询。

通过上述声明,如果你访问 $customer->bigOrders, 它将只返回数额大于100的订单。如果想指定一个不同的限定值,使用如下代码:

$orders = $customer->getBigOrders(200)->all();

注意:关联方法返回一个 yii\db\ActiveQuery 实例。如果你以属性(类property)的方式来访问它,返回数据是一个 yii\db\ActiveRecord 实例、或者是ActiveRecord数组或为空(null)。比如, $customer->getOrders() 返回一个 ActiveQuery 实例,而$customer->orders 返回一个 Order 对象数组(或者是一个空数组,如果查询结果为空)。

中间表关联查询

有时候,一些数据表通过中间表(pivot table)关联在一起。为了声明这样的关系,我们可以定制 yii\db\ActiveQuery 对象,通过调用它的 via() 或 viaTable() 方法。

比如,如果订单表 order 和商品表 item 通过连接表 order_item关联,我们可以在 Order 类中声明 items 关系如下:

class Order extends \yii\db\ActiveRecord
{
 public function getItems()
 {
  return $this->hasMany(Item::className(), ['id' => 'item_id'])
   ->viaTable('order_item', ['order_id' => 'id']);
 }
}

via() 方法和 viaTable() 类似,不过第一个参数是在当前ActiveRecord类中声明的一个关系(relation)名,而不是中间表的名称。比如,上述 items 关系也可以用下面的方法进行声明:

class Order extends \yii\db\ActiveRecord
{
 public function getOrderItems()
 {
  return $this->hasMany(OrderItem::className(), ['order_id' => 'id']);
 }
 public function getItems()
 {
  return $this->hasMany(Item::className(), ['id' => 'item_id'])
   ->via('orderItems');
 }
}

希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。

PHP 相关文章推荐
PHP的范围解析操作符(::)的含义分析说明
Jul 03 PHP
php array_pop()数组函数将数组最后一个单元弹出(出栈)
Jul 12 PHP
PHP 设计模式之观察者模式介绍
Feb 22 PHP
discuz加密解密函数使用方法和中文注释
Jan 21 PHP
使用php记录用户通过搜索引擎进网站的关键词
Feb 13 PHP
PHP的Yii框架的基本使用示例
Aug 21 PHP
php投票系统之增加与删除投票(管理员篇)
Jul 01 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
Nov 14 PHP
PHP实现的激活用户注册验证邮箱功能示例
Jun 06 PHP
PHP批量删除jQuery操作
Jul 23 PHP
PHP流Streams、包装器wrapper概念与用法实例详解
Nov 17 PHP
PHP连接MySQL数据库三种实现方法
Dec 10 PHP
php 实现301重定向跳转实例代码
Jul 18 #PHP
PHP的openssl加密扩展使用小结(推荐)
Jul 18 #PHP
PHP多进程编程总结(推荐)
Jul 18 #PHP
php 指定范围内多个随机数代码实例
Jul 18 #PHP
php 解决substr()截取中文字符乱码问题
Jul 18 #PHP
Yii2中cookie用法示例分析
Jul 18 #PHP
PHP socket 模拟POST 请求实例代码
Jul 18 #PHP
You might like
PHP中用header图片地址 简单隐藏图片源地址
2008/04/09 PHP
一个PHP的String类代码
2010/04/20 PHP
php获取远程文件大小
2015/10/20 PHP
JavaScript实现Sleep函数的代码
2007/03/04 Javascript
js 鼠标点击事件及其它捕获
2009/06/04 Javascript
javascript 写的一个简单的timer
2009/07/30 Javascript
jQuery dialog 异步调用ashx,webservice数据的代码
2010/08/03 Javascript
写给想学习Javascript的朋友一点学习经验小结
2010/11/23 Javascript
JS按位非(~)运算符与~~运算符的理解分析
2011/07/31 Javascript
jsvascript图像处理—(计算机视觉应用)图像金字塔
2013/01/15 Javascript
jQuery实现的简单折叠菜单(折叠面板)效果代码
2015/09/16 Javascript
卸载安装Node.js与npm过程详解
2016/08/15 Javascript
Bootstrap时间选择器datetimepicker和daterangepicker使用实例解析
2016/09/17 Javascript
JQuery中解决重复动画的方法
2016/10/17 Javascript
基于vue2.0实现简单轮播图
2017/11/27 Javascript
jq.ajax+php+mysql实现关键字模糊查询(示例讲解)
2018/01/02 Javascript
微信小程序App生命周期详解
2018/01/31 Javascript
javascript将16进制的字符串转换为10进制整数hex
2020/03/05 Javascript
基于JavaScript获取url参数2种方法
2020/04/17 Javascript
[02:21]十步杀一人,千里不留行——DOTA2全新英雄天涯墨客展示
2018/08/29 DOTA
跟老齐学Python之集合的关系
2014/09/24 Python
使用Python编写简单网络爬虫抓取视频下载资源
2014/11/04 Python
Python视频爬虫实现下载头条视频功能示例
2018/05/07 Python
JavaScript中的模拟事件和自定义事件实例分析
2018/07/27 Python
使用python的pandas为你的股票绘制趋势图
2019/06/26 Python
python通过移动端访问查看电脑界面
2020/01/06 Python
tensorflow使用freeze_graph.py将ckpt转为pb文件的方法
2020/04/22 Python
用python查找统一局域网下ip对应的mac地址
2021/01/13 Python
Python爬虫爬取微博热搜保存为 Markdown 文件的源码
2021/02/22 Python
美国网上订购鲜花:FTD
2016/09/23 全球购物
标准化管理实施方案
2014/02/25 职场文书
政府领导干部个人对照检查材料思想汇报
2014/09/24 职场文书
优秀党员个人总结
2015/02/14 职场文书
在职证明格式样本
2015/06/15 职场文书
旅行社计调工作总结
2015/08/12 职场文书
浅谈Redis位图(Bitmap)及Redis二进制中的问题
2021/07/15 Redis