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 相关文章推荐
几种显示数据的方法的比较
Oct 09 PHP
PHP初学入门
Nov 19 PHP
mysql_fetch_row,mysql_fetch_array,mysql_fetch_assoc的区别
Apr 24 PHP
使用php+apc实现上传进度条且在IE7下不显示的问题解决方法
Apr 25 PHP
PHP中file_exists()判断中文文件名无效的解决方法
Nov 12 PHP
php生成excel列名超过26列大于Z时的解决方法
Dec 29 PHP
PHP实现简单实用的分页类代码
Apr 08 PHP
golang与PHP输出excel示例
Jul 22 PHP
php 无限分类 树形数据格式化代码
Oct 11 PHP
PHP多个图片压缩成ZIP的方法
Aug 18 PHP
JS操作XML中DTD介绍及使用方法分析
Jul 04 PHP
TP5框架安全机制实例分析
Apr 05 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脚本加密专家php解密算法
2020/09/13 PHP
PHP SplObjectStorage使用实例
2015/05/12 PHP
使用prototype.js进行异步操作
2007/02/07 Javascript
childNodes.length与children.length的区别
2009/05/14 Javascript
Jquery ui css framework
2010/06/28 Javascript
javascript 得到文件后缀名的思路及实现
2020/05/09 Javascript
js(jQuery)获取时间的方法及常用时间类搜集
2013/10/23 Javascript
Javascript全局变量var与不var的区别深入解析
2013/12/09 Javascript
javascript面向对象之共享成员属性与方法及prototype关键字用法
2015/01/13 Javascript
JavaScript知识点总结(六)之JavaScript判断变量数据类型
2016/05/31 Javascript
jQuery旋转插件jqueryrotate用法详解
2016/10/13 Javascript
vue-hook-form使用详解
2017/04/07 Javascript
Easyui在treegrid添加控件的实现方法
2017/06/23 Javascript
JavaScript严格模式下关于this的几种指向详解
2017/07/12 Javascript
Angular 5.x 学习笔记之Router(路由)应用
2018/04/08 Javascript
JS基于封装函数实现的表格分页完整示例
2018/06/26 Javascript
Bootstrap table表格初始化表格数据的方法
2018/07/25 Javascript
layui问题之模拟select点击事件的实例讲解
2018/08/15 Javascript
axios全局注册,设置token,以及全局设置url请求网段的方法
2018/09/25 Javascript
移动端底部导航固定配合vue-router实现组件切换功能
2019/06/13 Javascript
vue实现几秒后跳转新页面代码
2020/09/09 Javascript
给你选择Python语言实现机器学习算法的三大理由
2017/11/15 Python
对numpy 数组和矩阵的乘法的进一步理解
2018/04/04 Python
pandas 按照特定顺序输出的实现代码
2018/07/10 Python
对pycharm代码整体左移和右移缩进快捷键的介绍
2018/07/16 Python
详解python中的异常捕获
2020/12/15 Python
css3中background新增的4个新的相关属性用法介绍
2013/09/26 HTML / CSS
廉价航班、机票和酒店:JustFly
2018/02/07 全球购物
高尔夫球鞋、服装、手套和装备:FootJoy
2018/12/15 全球购物
介绍一些UNIX常用简单命令
2014/11/11 面试题
安全生产管理合理化建议书
2014/03/12 职场文书
《陈涉世家》教学反思
2014/04/12 职场文书
十八大演讲稿
2014/05/22 职场文书
狂人日记读书笔记
2015/06/30 职场文书
教师节表彰会主持词
2015/07/06 职场文书
Java elasticsearch安装以及部署教程
2021/06/28 Java/Android