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 相关文章推荐
BBS(php & mysql)完整版(六)
Oct 09 PHP
数字转英文
Dec 06 PHP
PHP STRING 陷阱原理说明
Jul 24 PHP
PHP 时间日期操作实战
Aug 26 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
Jun 23 PHP
基于CakePHP实现的简单博客系统实例
Jun 28 PHP
PHP结合Jquery和ajax实现瀑布流特效
Jan 07 PHP
PHP基于正则批量替换Img中src内容实现获取缩略图的功能示例
Jun 07 PHP
php数据库的增删改查 php与javascript之间的交互
Aug 31 PHP
PHP实现基于3DES算法加密解密字符串示例
Aug 24 PHP
Ajax+PHP实现的删除数据功能示例
Feb 12 PHP
PHP通过调用新浪API生成t.cn格式短网址链接的方法详解
Feb 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动态生成javascript文件的2个例子
2014/04/11 PHP
PHP删除数组中指定下标的元素方法
2018/02/03 PHP
解决php extension 加载顺序问题
2019/08/16 PHP
使用nodejs、Python写的一个简易HTTP静态文件服务器
2014/07/18 NodeJs
jQuery通过控制节点实现仅在前台通过get方法完成参数传递
2015/02/02 Javascript
HTML5实现微信拍摄上传照片功能
2017/04/21 Javascript
详解Angular2组件之间如何通信
2017/06/22 Javascript
详解javascript中的变量提升和函数提升
2018/05/24 Javascript
前后端如何实现登录token拦截校验详解
2018/09/03 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
2018/10/30 Javascript
Vue动态组件和异步组件原理详解
2019/05/06 Javascript
VUE 单页面使用 echart 窗口变化时的用法
2020/07/30 Javascript
[01:11:02]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python益智游戏计算汉诺塔问题示例
2014/03/05 Python
Python实现快速排序和插入排序算法及自定义排序的示例
2016/02/16 Python
Python使用OpenCV进行标定
2018/05/08 Python
python 数字类型和字符串类型的相互转换实例
2018/07/17 Python
基于python实现简单日历
2018/07/28 Python
实例分析python3实现并发访问水平切分表
2018/09/29 Python
Python UnboundLocalError和NameError错误根源案例解析
2018/10/31 Python
python 递归调用返回None的问题及解决方法
2020/03/16 Python
python opencv实现图片缺陷检测(讲解直方图以及相关系数对比法)
2020/04/07 Python
pyecharts在数据可视化中的应用详解
2020/06/08 Python
利用CSS3实现平移动画效果示例代码
2016/10/12 HTML / CSS
英国高档时尚男装购物网站:MR PORTER
2016/08/09 全球购物
军用级手机壳,专为冒险而建:Zizo Wireless
2019/08/07 全球购物
Eclipse面试题
2014/03/22 面试题
斯福泰克软件测试面试题
2015/02/16 面试题
信息部岗位职责
2013/11/12 职场文书
事务机电主管工作职责
2014/02/25 职场文书
扩大国家免疫规划实施方案
2014/03/21 职场文书
科技活动周标语
2014/10/08 职场文书
餐饮服务员岗位职责
2015/02/09 职场文书
初中军训感想
2015/08/07 职场文书
感恩信:写给爸爸妈妈的一封感谢信
2019/09/12 职场文书
MySQL一些常用高级SQL语句
2021/07/03 MySQL