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 相关文章推荐
用Flash图形化数据(二)
Oct 09 PHP
PHP 操作文件的一些FAQ总结
Feb 12 PHP
使用PHPMYADMIN操作mysql数据库添加新用户和数据库的方法
Apr 02 PHP
php下使用iconv需要注意的问题
Nov 20 PHP
PHP快速按行读取CSV大文件的封装类分享(也适用于其它超大文本文件)
Apr 10 PHP
改写ThinkPHP的U方法使其路由下分页正常
Jul 02 PHP
浅析PHP中Session可能会引起并发问题
Jul 23 PHP
php 数组随机取值的简单实例
May 23 PHP
php版银联支付接口开发简明教程
Oct 14 PHP
php微信开发之图片回复功能
Jun 14 PHP
PHP hebrev()函数用法讲解
Feb 21 PHP
php+websocket 实现的聊天室功能详解
May 27 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制作静态网站的模板框架(四)
2006/10/09 PHP
简单的用PHP编写的导航条程序
2006/10/09 PHP
PHP获取和操作配置文件php.ini的几个函数介绍
2013/06/24 PHP
php根据操作系统转换文件名大小写的方法
2014/02/24 PHP
Symfony2联合查询实现方法
2016/03/18 PHP
浅谈thinkphp的nginx配置,以及重写隐藏index.php入口文件方法
2019/10/12 PHP
TreeView 用法(有代码)(asp.net)
2011/07/15 Javascript
jquery学习笔记 用jquery实现无刷新登录
2011/08/08 Javascript
JS选中checkbox后获取table内一行TD所有数据的方法
2015/07/01 Javascript
js自定义select下拉框美化特效
2016/05/12 Javascript
picLazyLoad 实现图片延时加载(包含背景图片)
2016/07/21 Javascript
js点击按钮实现水波纹效果代码(CSS3和Canves)
2016/09/15 Javascript
Vue.js组件tab实现选项卡切换
2020/03/23 Javascript
微信小程序 template模板详解及实例代码
2017/03/09 Javascript
JavaScript实现焦点进入文本框内关闭输入法的核心代码
2017/09/20 Javascript
提升node.js中使用redis的性能遇到的问题及解决方法
2018/10/30 Javascript
jQuery实现的简单日历组件定义与用法示例
2018/12/24 jQuery
vue表单验证你真的会了吗?vue表单验证(form)validate
2019/04/07 Javascript
Python内置函数 next的具体使用方法
2017/11/24 Python
代码分析Python地图坐标转换
2018/02/08 Python
Python子类继承父类构造函数详解
2019/02/19 Python
python爬取微信公众号文章的方法
2019/02/26 Python
Python从列表推导到zip()函数的5种技巧总结
2019/10/23 Python
加拿大租车网站:Enterprise Rent-A-Car
2018/07/26 全球购物
在C语言中实现抽象数据类型什么方法最好
2014/06/26 面试题
高三家长寄语
2014/04/03 职场文书
高中生第一学年自我鉴定2015
2014/09/28 职场文书
党员剖析材料范文
2014/12/18 职场文书
幼师辞职信范文大全
2015/05/12 职场文书
企业宣传稿范文
2015/07/23 职场文书
2016年植树节红领巾广播稿
2015/12/17 职场文书
合同补充协议书
2016/03/24 职场文书
Java elasticsearch安装以及部署教程
2021/06/28 Java/Android
opencv检测动态物体的实现
2021/07/21 Python
Oracle 触发器trigger使用案例
2022/02/24 Oracle
javascript进阶篇深拷贝实现的四种方式
2022/07/07 Javascript