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 相关文章推荐
PHP4实际应用经验篇(9)
Oct 09 PHP
php中常用编辑器推荐
Jan 02 PHP
php添加文章时生成静态HTML文章的实现代码
Feb 17 PHP
thinkphp循环结构用法实例
Nov 24 PHP
为PHP5.4开启Zend OPCode缓存
Dec 26 PHP
PHP使用Pthread实现的多线程操作实例
Nov 14 PHP
Symfony2使用第三方库Upload制作图片上传实例详解
Feb 04 PHP
php使用ffmpeg向视频中添加文字字幕的实现方法
May 23 PHP
PHP中header用法小结
May 23 PHP
Yii2 RESTful中api的使用及开发实例详解
Jul 06 PHP
ThinkPHP5 的简单搭建和使用详解
Nov 15 PHP
PHP判断是否是json字符串
Apr 01 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+MYSQL会员系统的登陆即权限判断实现代码
2011/09/23 PHP
学习php设计模式 php实现工厂模式(factory)
2015/12/07 PHP
Yii框架核心组件类实例详解
2019/08/06 PHP
php 实现银联商务H5支付的示例代码
2019/10/12 PHP
获取数组中最大最小值方法js代码(自写)
2013/08/12 Javascript
新增加的内容是如何将div的scrollbar自动移动最下面
2014/01/02 Javascript
jQuery中clearQueue()方法用法实例
2014/12/29 Javascript
js实现点击链接后窗口缩小并居中的方法
2015/03/02 Javascript
js中this用法实例详解
2015/05/05 Javascript
js实现防止被iframe的方法
2015/07/03 Javascript
干货分享:让你分分钟学会javascript闭包
2015/12/25 Javascript
js实现内容显示并使用json传输数据
2016/03/16 Javascript
jquery插件autocomplete用法示例
2016/07/01 Javascript
原生JS上传大文件显示进度条 php上传文件代码
2020/03/27 Javascript
详解vue-cli项目中用json-sever搭建mock服务器
2017/11/02 Javascript
vue里input根据value改变背景色的实例
2018/09/29 Javascript
通过js实现压缩图片上传功能
2020/02/25 Javascript
微信小程序点击滚动到指定位置的实现
2020/05/22 Javascript
详解JavaScript的this指向和绑定
2020/09/08 Javascript
使用Python脚本来控制Windows Azure的简单教程
2015/04/16 Python
python字符串中的单双引
2017/02/16 Python
python3.4+pycharm 环境安装及使用方法
2019/06/13 Python
Python基于httpx模块实现发送请求
2020/07/07 Python
python的flask框架难学吗
2020/07/31 Python
基于HTML5 的人脸识别活体认证的实现方法
2016/06/22 HTML / CSS
美国知名的女性服饰品牌:LOFT(洛芙特)
2016/08/05 全球购物
英国在线药房:Express Chemist
2019/03/28 全球购物
酒店服务与管理毕业生求职信
2013/11/02 职场文书
自我评价范文点评
2013/12/04 职场文书
毕业生的自我评价分享
2013/12/18 职场文书
工商管理毕业生推荐信
2013/12/24 职场文书
葛优非诚勿扰搞笑征婚台词
2014/03/17 职场文书
单位实习介绍信
2015/05/05 职场文书
繁星春水读书笔记
2015/06/30 职场文书
小学班长竞选稿
2015/11/20 职场文书
python process模块的使用简介
2021/05/14 Python