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高手?学会“懒惰”的编程
Dec 05 PHP
URL Rewrite的设置方法
Jan 02 PHP
Mysql中limit的用法方法详解与注意事项
Apr 19 PHP
PHP日期时间函数的高级应用技巧
May 16 PHP
php socket实现的聊天室代码分享
Aug 16 PHP
PHP7正式版测试,性能惊艳!
Dec 08 PHP
PHP5.3连接Oracle客户端及PDO_OCI模块的安装方法
May 13 PHP
PHP实现活动人选抽奖功能
Apr 19 PHP
php模仿qq空间或朋友圈发布动态、评论动态、回复评论、删除动态或评论的功能(中)
Jun 11 PHP
php实现统计二进制中1的个数算法示例
Jan 23 PHP
PHP时间戳和日期相互转换操作实例小结
Dec 18 PHP
PHP 自动加载类原理与用法实例分析
Apr 14 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设计模式  Command(命令模式)
2011/06/17 PHP
简单的php文件上传(实例)
2013/10/27 PHP
php输出指定时间以前时间格式的方法
2015/03/21 PHP
thinkphp关于简单的权限判定方法
2017/04/03 PHP
php面向对象程序设计入门教程
2019/06/22 PHP
PHP实现的抓取小说网站内容功能示例
2019/06/27 PHP
用一段js程序来实现动画功能
2007/03/06 Javascript
得到文本框选中的文字,动态插入文字的js代码
2007/03/07 Javascript
Juqery Html(),append()等方法的Bug解决方法
2010/12/13 Javascript
jQuery(1.6.3) 中css方法对浮动的实现缺陷分析
2011/09/09 Javascript
jQuery数组处理代码详解(含实例演示)
2012/02/03 Javascript
JS函数实现动态添加CSS样式表文件
2012/12/15 Javascript
jquery ready函数、css函数及text()使用示例
2013/09/27 Javascript
jQuery 写的简单打字游戏可以提示正确和错误的次数
2014/07/01 Javascript
一个JavaScript处理textarea中的字符成每一行实例
2014/09/22 Javascript
js实现iPhone界面风格的单选框和复选框按钮实例
2015/08/18 Javascript
javascript入门之window对象【新手必看】
2016/11/22 Javascript
JavaScript利用正则表达式替换字符串中的内容
2016/12/12 Javascript
jQuery展示表格点击变色、全选、删除
2017/01/05 Javascript
Node.js使用orm2进行update操作时关联字段无法修改的解决方法
2017/06/13 Javascript
JavaScript中递归实现的方法及其区别
2017/09/12 Javascript
node实现的爬虫功能示例
2018/05/04 Javascript
使用Webpack 搭建 Vue3 开发环境过程详解
2020/07/28 Javascript
[45:59]EG vs OG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/18 DOTA
Python3读取UTF-8文件及统计文件行数的方法
2015/05/22 Python
深入解读Python解析XML的几种方式
2016/02/16 Python
Python3 模块、包调用&路径详解
2017/10/25 Python
Python之使用adb shell命令启动应用的方法详解
2019/01/07 Python
解决Python找不到ssl模块问题 No module named _ssl的方法
2019/04/29 Python
Python实现井字棋小游戏
2020/03/09 Python
英语系本科生个人求职信
2013/09/21 职场文书
《青蛙看海》教学反思
2014/04/23 职场文书
2015年入党决心书
2015/02/05 职场文书
2015年六一儿童节演讲稿
2015/03/19 职场文书
物流仓管员岗位职责
2015/04/01 职场文书
夏洛特的网观后感
2015/06/15 职场文书