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 获取mysql数据库信息代码
Mar 12 PHP
关于使用coreseek并为其做分页的介绍
Jun 21 PHP
php环境无法上传文件的解决方法
Apr 30 PHP
php中的四舍五入函数代码(floor函数、ceil函数、round与intval)
Jul 14 PHP
PHP动态输出JavaScript代码实例
Feb 12 PHP
smarty模板引擎之配置文件数据和保留数据
Mar 30 PHP
php示例详解Constructor Prototype Pattern 原型模式
Oct 15 PHP
Thinkphp实现自动验证和自动完成
Dec 19 PHP
PHP中addcslashes与stripcslashes函数用法分析
Jan 07 PHP
功能强大的php分页函数
Jul 20 PHP
laravel 5.1下php artisan migrate的使用注意事项总结
Jun 07 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代码中使用换行及(\n或\r\n和br)的应用
2013/02/02 PHP
对PHP依赖注入的理解实例分析
2016/10/09 PHP
PHP框架Laravel中实现supervisor执行异步进程的方法
2017/06/07 PHP
Yii框架安装简明教程
2020/05/15 PHP
jQuery 方法大全方便学习参考
2010/02/25 Javascript
iframe自适应宽度、高度 ie6 7 8,firefox 3.86下测试通过
2010/07/29 Javascript
用jquery实现自定义风格的滑动条实现代码
2011/04/26 Javascript
禁用JavaScript控制台调试的方法
2014/03/07 Javascript
当滚动条滚动到页面底部自动加载增加内容的js代码
2014/05/13 Javascript
浅析Javascript的自动分号插入(ASI)机制
2016/09/29 Javascript
学习JavaScript图片预加载模块
2016/11/07 Javascript
js实现一个猜数字游戏
2017/03/31 Javascript
详解Vue双向数据绑定原理解析
2017/09/11 Javascript
Vue2.0 axios前后端登陆拦截器(实例讲解)
2017/10/27 Javascript
layui获取选中行数据的实例讲解
2018/08/19 Javascript
NodeJS搭建HTTP服务器的实现步骤
2018/10/12 NodeJs
JavaScript函数式编程(Functional Programming)组合函数(Composition)用法分析
2019/05/22 Javascript
深入理解 TypeScript Reflect Metadata
2019/12/12 Javascript
[06:43]2018DOTA2国际邀请赛寻真——VGJ.Thunder
2018/08/11 DOTA
Python之str操作方法(详解)
2017/06/19 Python
Python排序搜索基本算法之插入排序实例分析
2017/12/11 Python
解决每次打开pycharm直接进入项目的问题
2018/10/28 Python
python实践项目之监控当前联网状态详情
2019/05/23 Python
Python使用Pandas库实现MySQL数据库的读写
2019/07/06 Python
python实现字符串完美拆分split()的方法
2019/07/16 Python
Django stark组件使用及原理详解
2019/08/22 Python
Pandas读取csv时如何设置列名
2020/06/02 Python
Python3.7安装PyQt5 运行配置Pycharm的详细教程
2020/10/15 Python
英国在线药房:Chemist.co.uk
2019/03/26 全球购物
财务会计毕业生自荐信
2013/11/02 职场文书
优秀教师演讲稿
2014/05/06 职场文书
高校教师个人总结
2015/02/10 职场文书
教师节晚会主持词
2015/06/30 职场文书
2015年店长个人工作总结
2015/10/23 职场文书
详解Html5项目适配系统深色模式方案总结
2021/04/14 HTML / CSS
TypeScript中条件类型精读与实践记录
2021/10/05 Javascript