ThinkPHP一对一关联模型的运用(ORM)

embedded/2024/10/22 14:03:43/

一、序言

最近在写ThinkPHP关联模型的时候一些用法总忘,我就想通过写博客的方式复习和整理下一些用法。

具体版本:

  • topthink/framework:6.1.4
  • topthink/think-orm:2.0.61

二、实例应用

1、一对一关联

1.1、我先设计了两张表,分别为用户表(user),用户扩展表(user_extend)

1.2、分别给两个表建立模型

<?php
/*** Created by PhpStorm* Author: fengzi* Date: 2023/12/19* Time: 14:50*/namespace app\common\model;/*** 用户模型*/
class UserModel extends ComBaseModel
{protected $name='user';/*** 关联的用户扩展表* hasOne的第一个参数是要关联的模型类名,第二个参数是关联的外键名,第三个参数是当前模型(userModel)的主键名* @return \think\model\relation\HasOne* @Author: fengzi* @Date: 2024/6/27 17:38*/public function userExtend(){return $this->hasOne(UserExtendModel::class,'user_id','id');}
}
<?php
/*** Created by PhpStorm* Author: fengzi* Date: 2023/12/19* Time: 14:50*/namespace app\common\model;/*** 用户扩展表*/
class UserExtendModel extends ComBaseModel
{protected $name='user_extend';/*** 用户模型的相对关联* belongsTo的第一个参数是关联模型类名,第二个参数是当前模型(UserExtendModel)的外键,第三个参数是关联表的主键* @return \think\model\relation\BelongsTo* @Author: fengzi* @Date: 2024/6/27 17:41*/public function user(){return $this->belongsTo(UserModel::class,'user_id','id');}
}

1.3、with() 关联查询

一对一关联查询,user表对user_extend表使用的hasOne,使用hasWhere查询user_extend表时,相当于把user_extend表中符合查询条件的user_id集合作为user表的查询条件。

因为使用的一对一关联,所以当user_extend没找到对应查询数据时,user表也不会有数据。

注意:

  • hasWhere() 的第一个参数一定是user模型中关联用户扩展表的方法名称。
  • with预载入查询中的关联模型中的名称是user模型中关联用户扩展表的方法名称,如果方法名是驼峰写法,也可以转换成下划线。如:userExtend => user_extend
<?php
/*** Created by PhpStorm* Author: fengzi* Date: 2024/6/26* Time: 17:13*/namespace app\admin\controller\orm;use app\common\model\UserModel;class OrmController
{/*** @var UserModel|object|\think\App*/private UserModel $userModel;public function __construct(){$this->userModel = app(UserModel::class);}public function index(){/*** with 关联查询一对一* hasWhere第四个参数joinType的值:LEFT、RIGHT 或 INNER* user表对user_extend表使用的hasOne* 使用hasWhere查询user_extend表时,相当于把user_extend表中符合查询条件的user_id集合作为user表的查询条件。* 因为使用的一对一关联,所以当user_extend没找到对应查询数据时,user表也不会有数据*/$lists = $this->userModel->with(['user_extend'])->hasWhere('userExtend', function ($query){$query->where('organize_id', 1);}, '*', 'LEFT')->select()->toArray();// 输出打印dd($lists);}
}

1.3.1、查询结果展示

1.4、withJoin() 的查询( 我在user模型中定义的user_extend表的关联方法名称为userExtend ):

  • withJoin(['user_extend”]):这种写法查询出来的关联表数据会和主表数据在同一层级。而关联表数据的展现方式会以user模型中定义的关联方法名称为前缀+下划线+表字段的形式呈现。
    • 注意:【userExtend__xxx】中的下划线是两个,并不是一个下划线(一个下划线 _      ;两个下划线 __ )。所以在查询结果对象转换成数组后去获取字段数据时要注意,避免报错。
    • 这个写法同级中还多了一个【user_extend】字段,其值为null。这个字段在两个数据表中都是不存在的。
  • withJoin(['userExtend”]):这种写法査询出来的关联表数据与主表数据是有父子级关系。以withJoin中定义的模型名称“userExtend”作为主表的一个字段,把关联表的数据放入这个字段中。
public function index()
{// 实例化模型$userModel = app(UserModel::class);/*** 联表数据和主表数据在同一级*/$info = $userModel->withJoin(['user_extend'])->find(1);dump($info->toArray());/*** 联表数据是主表数据的一个子级,主/联表数据呈现父子级关系*/$info = $userModel->withJoin(['userExtend'])->find(1);dd($info->toArray());
}

1.4.1、withJoin的条件查询注意事项:

  • 使用 withJoin() 做关联,进行条件查询的时候,只要使用 where() 方法进行条件筛选即可。
  • 如果主/联表中有相同的字段且筛选条件就是相同的字段,使用 hasWhere() 方法进行条件筛选会报错。
  • 如果主/联表中有相同的字段且筛选条件是主表中的字段,那么where条件应该这么写【where(['mkl_user.role_id'=>2])】。同时参数中的role_id要写明是哪个表,且带上表前缀。
  • 如果主/联表中有相同的字段且筛选条件是联表中的字段,那么where条件应该这么写【where(['userExtend.role_id'=>3])】。同时参数中的role_id要写明是哪个关联表,关联名称跟【withJoin('userExtend')】的一样。
public function index()
{// 实例化模型$userModel = app(UserModel::class);/*** where(['organize_id'=>3])* 可以根据条件查询出结果*** hasWhere('userExtend', function ($query){*     $query->where('organize_id', 3);* }, '*', 'LEFT')* 不能查询出结果,报错“Illegal offset type”*/$info = $userModel->withJoin(['user_extend'])->where(['organize_id'=>3])/*->hasWhere('user_extend', function ($query){$query->where('organize_id', 3);})*/->select();/*********** 以下是主/联表有相同字段(role_id字段相同)时的查询方式 ***********/

// 要筛选主表(user表)中的相同字段时$info = $userModel->withJoin('userExtend')->where(['mkl_user.role_id'=>2])->select();// 输出打印dump($info->toArray());// 要筛选关联表(user_extend表)中的相同字段时$extendInfo = $userModel->withJoin('userExtend')->where(['userExtend.role_id'=>3])->select();// 输出打印dd($extendInfo->toArray()); }

1.5、with 关联修改

关联修改的常见形式有两种:

  • 方式一:把关联表要修改的数据写入一个数组中,使用save方法直接修改。
  • 方式二:单独字段一个个赋值后,最后使用save方法进行修改。

注意:

  • 不管是上面哪种,查询出来的对象不能转换成数组后进行关联表的修改,不然就会报错。
  • with中的关联名称一般要与修改时一致。当然,不一致也可以,写模型中关联方法的名称也行。如:with使用user_extend,修改时使用userExtend也是可以的。
public function index()
{// 关联查询$info = $this->userModel->with(['user_extend'])->find(1);// 输出打印dump($info->toArray());// 关联修改:方式一/*$userExtend = ['email' => '88888888@qq.com','gender' => 1,];$info->user_extend->save($userExtend);*/// 关联修改:方式二$info->userExtend->email = '88888888@qq.com';$info->userExtend->gender = 0;$info->userExtend->save();// 再次关联查询$newInfo = $this->userModel->with(['user_extend'])->find(1);// 输出打印dd($newInfo->toArray());
}

1.5.1、with关联修改后的结果

1.6、关联删除

关联删除这里有一些小细节需要注意,下面我们用user_id=1的用户来试验。下图user_id=1的用户数据目前是没有删除的。

1.6.1、with 的关联删除

(1)这种写法能正确的删除主表和关联表的数据,需要注意的是【 with(['userExtend']) 】和【 together(['userExtend']) 】中的参数名称要一样,不能一个驼峰【userExtend】写法,另一个下划线【user_extend】写法。要么都写【userExtend】,要么都写【user_extend】。

public function index()
{// 实例化模型$userModel = app(UserModel::class);// 查询用户ID=1的数据$info = $userModel->with(['userExtend'])->find(1);// 删除主表和关联表$del = $info->together(['userExtend'])->delete();
}

(2)这种写法在查询的时候没有带 with() 方法,那么在删除数据的时候,只能删除主表数据,关联表数据不会删除。

public function index()
{// 实例化模型$userModel = app(UserModel::class);// 查询用户ID=1的数据$info = $userModel->find(1);// 删除主表和关联表$del = $info->together(['userExtend'])->delete();// 输出打印dd($del);
}

注意:当主表的数据已经被删除后,还调用 together() 进行主/联表的数据删除就会报错。

(3)当前代码中的方式一和方式二其实跟上面介绍的没什么区别,只是上面几个写法的链式操作。

  • 方式一:只能删除主表数据,关联表数据不会删除。
  • 方式二:可以同时删除主表和关联表的数据。
public function index()
{// 实例化模型$userModel = app(UserModel::class);// 删除主表和关联表// 方式一$del = $userModel->find(1)->together(['userExtend'])->delete();// 方式二$del = $userModel->with(['userExtend'])->find(1)->together(['userExtend'])->delete();
}

1.6.2、withJoin 的关联删除

注意:

  • 如果要主/联表的数据都删除,那么在查询的时候必须带 withJoin() 方法。
  • 带 withJoin() 方法查询后,删除时 together() 和 withJoin() 方法的参数必须是 UserModel 模型中关联的方法名称,即本文1.2处的userExtend() 方法的名称。
  • 如果不带 withJoin() 方法查询后,想要删除主/联表的数据是不可行的,这时删除只会删主表数据,联表数据是不会删除。
public function index()
{// 实例化模型$userModel = app(UserModel::class);/*** withJoin(['user_extend'])  together(['userExtend'])   主表数据删除,联表数据不会删除* withJoin(['user_extend'])  together(['user_extend'])  主表数据删除,联表数据不会删除* withJoin(['userExtend'])  together(['userExtend'])    主表数据删除,联表数据删除* withJoin(['userExtend'])  together(['user_extend'])   主表数据删除,联表数据不会删除*/// 查询用户ID=1的数据$info = $userModel->withJoin(['userExtend'])->find(1);// 删除主表和关联表$del = $info->together(['userExtend'])->delete();

/*** together(['user_extend'])  主表数据删除,联表数据不会删除* together(['userExtend'])   主表数据删除,联表数据不会删除*/// 查询用户ID=1的数据$info = $userModel->find(1);// 删除主表和关联表$del = $info->together(['userExtend'])->delete(); }

http://www.ppmy.cn/embedded/86663.html

相关文章

深入解析Perl的正则表达式:功能、应用与技巧

在编程世界中&#xff0c;正则表达式是一种强大的文本处理工具&#xff0c;它能够用于搜索、替换、匹配字符串等操作。Perl语言以其强大的文本处理能力著称&#xff0c;而其正则表达式功能更是其核心特性之一。本文将深入探讨Perl中的正则表达式&#xff0c;包括其基本语法、应…

photoshop学习笔记——移动工具

移动工具&#xff0c;可以对图层进行移动&#xff0c;快捷键 V 使用的素材已经放上了&#xff0c;直接下载即可 按住ctrl 可以自动选取&#xff0c;鼠标点击哪个对象&#xff0c;自动选中哪个图层 按住 shift 校正角度&#xff08;只能沿着直线移动&#xff09; 按住 alt 拖…

小阿轩yx-FastDFS分布式存储

小阿轩yx-FastDFS分布式存储 FastDFS简介 是一个开源的轻量级分布式文件系统它对文件进行管理解决了大容量存储和负载均衡的问题特别适合以文件为载体的在线服务充分考虑了冗余备份、负载均衡、线性扩容机制注重高可用、高性能指标很容易搭建一套高性能的文件服务器集群提供文…

昇思25天学习打卡营第17天|计算机视觉

昇思25天学习打卡营第17天 文章目录 昇思25天学习打卡营第17天ShuffleNet图像分类ShuffleNet网络介绍模型架构Pointwise Group ConvolutionChannel ShuffleShuffleNet模块构建ShuffleNet网络 模型训练和评估训练集准备与加载模型训练模型评估模型预测 打卡记录 ShuffleNet图像分…

基于FPGA的数字信号处理导航

之前闲暇的时候也看过一些数字信号处理和调制解调的原理及FPGA实现&#xff0c;不管是DDS、FIR、IIR滤波器&#xff0c;还是ASK、FSK、上变频、下变频的实现&#xff0c;都是比较简单的&#xff08;仅限于实现&#xff0c;不做深入讨论&#xff09;&#xff0c;而这些算法使用F…

使用Python和Pandas导出SQLite数据到Excel的小工具

在数据处理和导出的日常工作中&#xff0c;有时我们需要将SQLite数据库中的数据导出到Excel文件以便进一步分析或分享。本文将介绍如何使用Python的wxPython、Pandas和SQLite3库创建一个小工具&#xff0c;实现从SQLite数据库中提取数据并将其导出到Excel文件的功能。 C:\pytho…

【python】批量读取Word文档中的特定表格并保存为Excel文件

批量读取Word文档中的特定表格并保存为Excel文件 在工作中&#xff0c;我们常常需要从多个Word文档中提取数据&#xff0c;然后将这些数据汇总到一个Excel文件中进行分析。下面&#xff0c;我将分享一个Python脚本&#xff0c;它可以从多个Word文档中读取特定的表格数据&#…

微信小程序开发入门指南

文章目录 一、微信小程序简介二、微信小程序开发准备三、微信小程序开发框架四、微信小程序开发实例六、微信小程序开发进阶6.1 组件化开发6.2 API调用6.3 云开发 七、微信小程序开发注意事项7.1 遵守规范7.2 注意性能7.3 保护用户隐私 八、总结 大家好&#xff0c;今天将为大家…