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的SQL注入实现(测试代码安全不错)
Feb 27 PHP
深入php socket的讲解与实例分析
Jun 13 PHP
ThinkPHP实现跨模块调用操作方法概述
Jun 20 PHP
PHP+FastCGI+Nginx配置PHP运行环境
Aug 07 PHP
PHP往XML中添加节点的方法
Mar 12 PHP
PHP使用mysqldump命令导出数据库
Apr 14 PHP
PHP中的类型提示(type hinting)功能介绍
Jul 01 PHP
PHP开发中解决并发问题的几种实现方法分析
Nov 13 PHP
PHP使用XMLWriter读写xml文件操作详解
Jul 31 PHP
PHP基于cookie实现统计在线人数功能示例
Jan 16 PHP
PHP CURL中传递cookie的方法步骤
May 09 PHP
Smarty模板配置实例简析
Jul 20 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将数据导入到Foxmail
2006/10/09 PHP
基于asp+ajax和数据库驱动的二级联动菜单
2010/05/06 PHP
php中的常用魔术方法总结
2013/08/02 PHP
php获取YouTube视频信息的方法
2015/02/11 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
php动态绑定变量的用法
2015/06/16 PHP
详解PHP的Laravel框架中Eloquent对象关系映射使用
2016/02/26 PHP
JavaScript中出现乱码的处理心得
2009/12/24 Javascript
Google (Local) Search API的简单使用介绍
2013/11/28 Javascript
JQuery中使用.each()遍历元素学习笔记
2014/11/08 Javascript
Easyui 之 Treegrid 笔记
2016/04/29 Javascript
JS跨域交互(jQuery+php)之jsonp使用心得
2016/07/01 Javascript
React中jquery引用的实现方法
2017/09/12 jQuery
用React实现一个完整的TodoList的示例代码
2017/10/30 Javascript
Vue中computed与methods的区别详解
2018/03/24 Javascript
关于vue-router的那些事儿
2018/05/23 Javascript
基于Vue实现可以拖拽的树形表格实例详解
2018/10/18 Javascript
JS实现textarea通过换行或者回车把多行数字分割成数组并且去掉数组中空的值
2018/10/29 Javascript
Js实现复选框的全选、全不选反选功能代码实例
2020/02/28 Javascript
python解析xml文件实例分享
2013/12/04 Python
修改默认的pip版本为对应python2.7的方法
2018/11/06 Python
python3实现点餐系统
2019/01/24 Python
Django中自定义查询对象的具体使用
2019/10/13 Python
TENSORFLOW变量作用域(VARIABLE SCOPE)
2020/01/10 Python
在Tensorflow中实现leakyRelu操作详解(高效)
2020/06/30 Python
Python子进程subpocess原理及用法解析
2020/07/16 Python
教你使用Sublime text3搭建Python开发环境及常用插件安装另分享Sublime text3最新激活注册码
2020/11/12 Python
pandas apply使用多列计算生成新的列实现示例
2021/02/24 Python
35款精致的 CSS3 和 HTML5 网页模板 推荐
2012/08/03 HTML / CSS
AmazeUI 点击元素显示全屏的实现
2020/08/25 HTML / CSS
Zooplus葡萄牙:欧洲领先的网上宠物商店
2018/07/01 全球购物
blueseventy官网:铁人三项和比赛泳衣
2021/02/06 全球购物
大专学生推荐信范文
2013/11/19 职场文书
电子信息科学专业自荐信
2014/01/30 职场文书
活动总结书
2014/05/08 职场文书
CSS link与@import的区别和用法解析
2023/05/07 HTML / CSS