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生成带有雪花背景的验证码
Sep 28 PHP
php 网页播放器用来播放在线视频的代码(自动判断并选择视频文件类型)
Jun 03 PHP
MySQL 日期时间函数常用总结
Jun 12 PHP
php中++i 与 i++ 的区别
Aug 08 PHP
解析PHP中empty is_null和isset的测试
Jun 29 PHP
支持中文和其他编码的php截取字符串函数分享(截取中文字符串)
Mar 13 PHP
PHP多文件上传类实例
Mar 07 PHP
php生成静态html页面的方法(2种方法)
Sep 14 PHP
PHP和MySql中32位和64位的整形范围是多少
Feb 18 PHP
简单谈谈PHP中strlen 函数
Feb 27 PHP
基于PHP常用文件函数和目录函数整理
Aug 17 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
Feb 29 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
APMServ使用说明
2006/10/23 PHP
php class中self,parent,this的区别以及实例介绍
2013/04/24 PHP
详解PHP防止直接访问.php 文件的实现方法
2017/07/28 PHP
利用jQuery 实现GridView异步排序、分页的代码
2010/02/06 Javascript
JavaScript 学习笔记之语句
2015/01/14 Javascript
JScript中的条件注释详解
2015/04/24 Javascript
jquery实现图片放大镜功能
2015/11/23 Javascript
jQuery unbind 删除绑定事件详解
2016/05/24 Javascript
Require.js的基本用法详解
2017/07/03 Javascript
vue实现前进刷新后退不刷新效果
2018/01/26 Javascript
写一个移动端惯性滑动&回弹Vue导航栏组件 ly-tab
2018/03/06 Javascript
VUE-cli3使用 svg-sprite-loader
2018/10/20 Javascript
mpvue+vant app搭建微信小程序的方法步骤
2019/02/11 Javascript
layer弹出层显示在top顶层的方法
2019/09/11 Javascript
纯 JS 实现放大缩小拖拽功能(完整代码)
2019/11/25 Javascript
使用setup.py安装python包和卸载python包的方法
2013/11/27 Python
使用Python神器对付12306变态验证码
2016/01/05 Python
Python解析最简单的验证码
2016/01/07 Python
pandas 快速处理 date_time 日期格式方法
2018/11/12 Python
python 获取url中的参数列表实例
2018/12/18 Python
Python实现的合并两个有序数组算法示例
2019/03/04 Python
Python:二维列表下标互换方式(矩阵转置)
2019/12/02 Python
Python安装并操作redis实现流程详解
2020/10/13 Python
python 爬虫网页登陆的简单实现
2020/11/30 Python
支票、地址标签、包装纸和慰问卡:Current Catalog
2018/01/30 全球购物
简单说说tomcat的配置
2013/05/28 面试题
Python里面如何实现tuple和list的转换
2012/06/13 面试题
中式面点餐厅创业计划书
2014/01/29 职场文书
道德演讲稿
2014/05/21 职场文书
新农村建设汇报材料
2014/08/15 职场文书
党员学习中共十八大思想报告
2014/09/12 职场文书
个人自我剖析材料
2014/09/30 职场文书
党支部先进事迹材料
2014/12/24 职场文书
2015年度绩效考核工作总结
2015/05/27 职场文书
推普标语口号大全
2015/12/26 职场文书
Python matplotlib 利用随机函数生成变化图形
2022/04/26 Python