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 相关文章推荐
中国站长站 For Dede4.0 采集规则
May 27 PHP
php URL编码解码函数代码
Mar 10 PHP
PHP 文件上传功能实现代码
Jun 24 PHP
PHP XML error parsing SOAP payload on line 1
Jun 17 PHP
微盾PHP脚本加密专家php解密算法
Sep 13 PHP
PHP 正则表达式小结
Feb 12 PHP
PHP使用CURL实现多线程抓取网页
Apr 30 PHP
ThinkPHP表单令牌错误的相关解决方法分析
May 20 PHP
PHP封装函数实现生成随机的字符串验证码
Jan 24 PHP
PHP基于迭代实现文件夹复制、删除、查看大小等操作的方法
Aug 11 PHP
PHP实现读取文件夹及批量重命名文件操作示例
Apr 15 PHP
PHP笛卡尔积实现原理及代码实例
Dec 09 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数组对百万数据进行排除重复数据的实现代码
2010/06/08 PHP
PHP使用MPDF类生成PDF的方法
2015/12/08 PHP
功能强大的php文件上传类
2016/08/29 PHP
PHP读MYSQL中文乱码的快速解决方法
2016/10/01 PHP
PHP生成图表pChart的示例解析
2020/07/31 PHP
JavaScript 版本自动生成文章摘要
2008/07/23 Javascript
javascript中style.left和offsetLeft的用法说明
2014/03/07 Javascript
JavaScript中setMonth()方法的使用详解
2015/06/11 Javascript
jquery实现横向图片轮播特效代码分享
2015/11/19 Javascript
javascript截图 jQuery插件imgAreaSelect使用详解
2016/05/04 Javascript
jQuery+PHP实现微信转盘抽奖功能的方法
2016/05/25 Javascript
Radio 单选JS动态添加的选项onchange事件无效的解决方法
2016/12/12 Javascript
Vue.js中数据绑定的语法教程
2017/06/02 Javascript
纯JavaScript实现实时反馈系统时间
2017/10/26 Javascript
JavaScript 对引擎、运行时、调用堆栈的概述理解
2018/10/22 Javascript
用jQuery实现抽奖程序
2020/04/12 jQuery
Python MySQLdb模块连接操作mysql数据库实例
2015/04/08 Python
Python Django中的STATIC_URL 设置和使用方式
2020/03/27 Python
Python发起请求提示UnicodeEncodeError错误代码解决方法
2020/04/21 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
2020/06/23 Python
解析Tensorflow之MNIST的使用
2020/06/30 Python
canvas拼图功能实现代码示例
2018/11/21 HTML / CSS
英国电器零售商:PRC Direct
2018/06/21 全球购物
宝拉珍选官方旗舰店:2%水杨酸精华液,收缩毛孔粗大和祛痘
2018/07/01 全球购物
Dr.Jart+美国官网:韩国药妆品牌
2019/01/18 全球购物
软件测试常见笔试题
2012/02/04 面试题
岗位职责范本
2013/11/23 职场文书
办公室前台岗位职责
2014/01/04 职场文书
小学音乐教学反思
2014/02/05 职场文书
《奇妙的国际互联网》 教学反思
2014/02/25 职场文书
2014年幼儿园保育工作总结
2014/12/02 职场文书
环卫个人总结
2015/03/03 职场文书
幼儿园六一儿童节主持词
2015/06/30 职场文书
导游词之香港-太平山顶
2019/10/18 职场文书
Nginx的rewrite模块详解
2021/03/31 Servers
Pygame Rect区域位置的使用(图文)
2021/11/17 Python