当前位置: 首页 > news >正文

ThinkPHP 一对多关联

用一对多关联的前提

多的一方的数据库表有一的一方数据库表的外键。

举例,用户获取自己的所有文章

数据表结构如下

// 用户表
useruser_id - integer  // 用户主键name - varchar // 用户名称// 文章表
articlearticle_id - integer // 文章主键title - varchar // 文章名标题content - text // 文章内容user_id - integer // 作者 user_id

多的一方(文章表)存在一的一方(用户表)的外键 user_id 。

一对多关联定义

用户表 user 模型:

<?phpnamespace app\api\model;class User extends Base
{// 不是默认主键名称记得定义 pk 属性protected $pk = 'user_id';// 获取用户详情以及用户的所有文章public static function getDetail(int $user_id){return self::get($user_id, 'articles');}// 一对多获取用户的文章public function articles(){// 完整写法return $this->hasMany('Article', 'user_id', 'user_id');}
}

hasMany 方法参数如下:

hasMany('关联模型', '关联模型外键', '当前模型主键');

除了关联模型外,其它参数都是可选。

  • 关联模型(必须):模型名或者模型类名
  • 关联模型外键:关联模型外键,默认的外键名规则是当前模型名+_id
  • 当前模型主键:当前模型主键,一般会自动获取也可以指定传入

实例演示

shop_article 表

 shop_user 表

演示1

获取 user_id 为 1 的用户详情以及用户的所有文章

用户 User 控制器

<?phpnamespace app\api\controller;use app\api\model\User as UserModel;class User extends Base
{public function detail(){$user_id = 1;$detail = UserModel::getDetail($user_id);echo '<pre>';var_dump($detail);echo '</pre>';}
}

用户表 User 模型

<?phpnamespace app\api\model;class User extends Base
{// 不是默认主键名称记得定义 pk 属性protected $pk = 'user_id';// 获取用户详情以及用户的所有文章public static function getDetail(int $user_id){return self::get($user_id, 'articles');}// 一对多获取用户的文章public function articles(){// 完整写法return $this->hasMany('Article', 'user_id', 'user_id');}
}

user 控制器  detail 方法输出

object(app\api\model\User)#41 (2) {["data"]=>array(4) {["user_id"]=>int(1)["name"]=>string(5) "admin"["create_time"]=>int(1688452509)["update_time"]=>int(1688452509)}["relation"]=>array(1) {["articles"]=>object(think\model\Collection)#50 (1) {["items":protected]=>array(2) {[0]=>object(app\api\model\Article)#45 (2) {["data"]=>array(6) {["article_id"]=>int(1)["title"]=>string(12) "测试标题"["content"]=>string(12) "测试内容"["user_id"]=>int(1)["create_time"]=>int(1689401566)["update_time"]=>int(1689401566)}["relation"]=>array(0) {}}[1]=>object(app\api\model\Article)#46 (2) {["data"]=>array(6) {["article_id"]=>int(2)["title"]=>string(13) "测试标题1"["content"]=>string(13) "测试内容1"["user_id"]=>int(1)["create_time"]=>int(1689498967)["update_time"]=>int(1689498967)}["relation"]=>array(0) {}}}}}
}

单条查询输出的是 User 模型实例,User 模型实例的 relation 属性(关联数组)保存着关联模型,在该关联数组中,关联方法名 articles 作为键名,关联查询结果作为键值(对一关联查询返回模型实例,对多关联查询返回结果集对象)。

使用的 SQL 如下

SELECT * FROM `shop_user` WHERE `user_id` = 1 LIMIT 1SELECT * FROM `shop_article` WHERE `user_id` = 1

获取当前用户的文章,访问 articles(关联方法名) 属性即可,如下

<?phpnamespace app\api\controller;use app\api\model\User as UserModel;class User extends Base
{public function detail(){$user_id = 1;$detail = UserModel::getDetail($user_id);echo '<pre>';var_dump($detail->articles);echo '</pre>';}
}

输出如下

object(think\model\Collection)#50 (1) {["items":protected]=>array(2) {[0]=>object(app\api\model\Article)#45 (2) {["data"]=>array(6) {["article_id"]=>int(1)["title"]=>string(12) "测试标题"["content"]=>string(12) "测试内容"["user_id"]=>int(1)["create_time"]=>int(1689401566)["update_time"]=>int(1689401566)}["relation"]=>array(0) {}}[1]=>object(app\api\model\Article)#46 (2) {["data"]=>array(6) {["article_id"]=>int(2)["title"]=>string(13) "测试标题1"["content"]=>string(13) "测试内容1"["user_id"]=>int(1)["create_time"]=>int(1689498967)["update_time"]=>int(1689498967)}["relation"]=>array(0) {}}}
}

演示2

获取所有用户的用户详情以及用户的所有文章

用户 User 控制器

<?phpnamespace app\api\controller;use app\api\model\User as UserModel;class User extends Base
{// 获取所有用户的用户详情以及用户的所有文章public function list(){$list = UserModel::getList();echo '<pre>';var_dump($list);echo '</pre>';}
}

用户表 User 模型

<?phpnamespace app\api\model;class User extends Base
{protected $pk = 'user_id';// 获取所有用户的用户详情以及用户的所有文章public static function getList(){return self::with('articles')->select();}// 一对多获取用户的文章public function articles(){// 完整写法return $this->hasMany('Article', 'user_id', 'user_id');}
}

user 控制器  list 方法输出

object(think\model\Collection)#44 (1) {["items":protected]=>array(3) {[0]=>object(app\api\model\User)#41 (2) {["data"]=>array(4) {["user_id"]=>int(1)["name"]=>string(5) "admin"["create_time"]=>int(1688452509)["update_time"]=>int(1688452509)}["relation"]=>array(1) {["articles"]=>object(think\model\Collection)#52 (1) {["items":protected]=>array(2) {[0]=>object(app\api\model\Article)#47 (2) {["data"]=>array(6) {["article_id"]=>int(1)["title"]=>string(12) "测试标题"["content"]=>string(12) "测试内容"["user_id"]=>int(1)["create_time"]=>int(1689401566)["update_time"]=>int(1689401566)}["relation"]=>array(0) {}}[1]=>object(app\api\model\Article)#48 (2) {["data"]=>array(6) {["article_id"]=>int(2)["title"]=>string(13) "测试标题1"["content"]=>string(13) "测试内容1"["user_id"]=>int(1)["create_time"]=>int(1689498967)["update_time"]=>int(1689498967)}["relation"]=>array(0) {}}}}}}[1]=>object(app\api\model\User)#42 (2) {["data"]=>array(4) {["user_id"]=>int(2)["name"]=>string(0) ""["create_time"]=>int(1689732287)["update_time"]=>int(1689732287)}["relation"]=>array(1) {["articles"]=>object(think\model\Collection)#53 (1) {["items":protected]=>array(0) {}}}}[2]=>object(app\api\model\User)#43 (2) {["data"]=>array(4) {["user_id"]=>int(3)["name"]=>string(6) "测试"["create_time"]=>int(1690355199)["update_time"]=>int(1690355199)}["relation"]=>array(1) {["articles"]=>object(think\model\Collection)#54 (1) {["items":protected]=>array(0) {}}}}}
}

多条查询返回的是 Collection(结果集)对象,Collection 对象的 item 属性保存着所有用户模型实例,每个用户模型实例的 relation 属性 (关联数组)属性保存着关联模型实例,关联方法名 articles 作为键名,结果集对象作为键值,结果集对象的 items 属性(索引数组)保存着关联查询结果。

使用的 SQL 如下

SELECT * FROM `shop_user`SELECT * FROM `shop_article` WHERE `user_id` IN (1,2,3)

获取每个用户的所有文章,访问 articles(关联方法名) 属性即可,如下

<?phpnamespace app\api\controller;use app\api\model\User as UserModel;class User extends Base
{public function list(){$list = UserModel::getList();foreach ($list as $user) {echo '<pre>';var_dump($user->articles);echo '</pre>';}}}

​​​​​​​

user 控制器 list 方法输出如下

object(think\model\Collection)#52 (1) {["items":protected]=>array(2) {[0]=>object(app\api\model\Article)#47 (2) {["data"]=>array(6) {["article_id"]=>int(1)["title"]=>string(12) "测试标题"["content"]=>string(12) "测试内容"["user_id"]=>int(1)["create_time"]=>int(1689401566)["update_time"]=>int(1689401566)}["relation"]=>array(0) {}}[1]=>object(app\api\model\Article)#48 (2) {["data"]=>array(6) {["article_id"]=>int(2)["title"]=>string(13) "测试标题1"["content"]=>string(13) "测试内容1"["user_id"]=>int(1)["create_time"]=>int(1689498967)["update_time"]=>int(1689498967)}["relation"]=>array(0) {}}}
}
object(think\model\Collection)#53 (1) {["items":protected]=>array(0) {}
}
object(think\model\Collection)#54 (1) {["items":protected]=>array(0) {}
}

如果觉得作者写得好,请帮我点个赞,谢谢。

相关文章:

ThinkPHP 一对多关联

用一对多关联的前提 多的一方的数据库表有一的一方数据库表的外键。 举例&#xff0c;用户获取自己的所有文章 数据表结构如下 // 用户表 useruser_id - integer // 用户主键name - varchar // 用户名称// 文章表 articlearticle_id - integer // 文章主键title - varchar …...

C++基础篇(二)基本数组及示例

目录 一、一维数组1、定义和初始化2、访问和修改3、元素逆置和冒泡排序 二、二维数组&#xff08;用指针进行访问与修改&#xff09;1、定义和初始化2、访问与修改 三、更高维度的数组1、三维数组2、高维数组 一、一维数组 1、定义和初始化 在 C 中&#xff0c;可以使用下面的…...

C++多态练习题

目录 一.习题1&#xff1a; 解决下列测试代码所出现的问题 测试用例1&#xff1a; 测试用例2&#xff1a; 代码改进&#xff1a; 习题1总结&#xff1a; 二.习题2. 求类对象的大小 三.习题3&#xff1a; 代码解析 &#xff1a; 解析图&#xff1a; 四.习题4&#xff…...

ELD透明屏在智能家居中有哪些优点展示?

ELD透明屏是一种新型的显示技术&#xff0c;它能够在不需要背光的情况下显示图像和文字。 ELD透明屏的原理是利用电致发光效应&#xff0c;通过在透明基板上涂覆一层特殊的发光材料&#xff0c;当电流通过时&#xff0c;发光材料会发出光线&#xff0c;从而实现显示效果。 ELD…...

第十三章 利用PCA简化数据

文章目录 第十三章 利用PCA简化数据13.1降维技术13.2PCA13.2.1移动坐标轴 13.2.2在NumPy中实现PCA13.3利用PCA对半导体制造数据降维 第十三章 利用PCA简化数据 PCA&#xff08;Principal Component Analysis&#xff0c;主成分分析&#xff09;是一种常用的降维技术&#xff0…...

开源中文分词Ansj的简单使用

ANSJ是由孙健&#xff08;ansjsun&#xff09;开源的一个中文分词器&#xff0c;为ICTLAS的Java版本&#xff0c;也采用了Bigram HMM分词模型&#xff1a;在Bigram分词的基础上&#xff0c;识别未登录词&#xff0c;以提高分词准确度。 虽然基本分词原理与ICTLAS的一样&#…...

251_多线程_创建一个多线程的图像处理应用,其中每个线程负责对一部分图像进行处理,然后将处理后的结果合并为最终图像

举一个更丰富的例子来说明多线程的用法。 我们将创建一个多线程的图像处理应用,其中每个线程负责对一部分图像进行处理,然后将处理后的结果合并为最终图像。 这个例子可以更好地展示多线程并发处理的优势。 假设有一个函数 processImageSection,它会对图像的一个特定区域进…...

[吐槽Edge浏览器]关于Edge浏览器的闪退问题

这个浏览器嘛&#xff0c;在谷歌浏览器不能页面翻译后&#xff0c;一直是用的高高兴兴的&#xff0c;可突然有一天&#xff0c;Edge浏览器页面加载不出来了。 很慌&#xff0c;大概就是页面崩溃、加载失败什么的都出现过。 修了整整一天&#xff0c;不知道原因在哪&#xff0c;…...

数据包在网络中传输的过程

ref: 【先把这个视频看完了】&#xff1a;数据包的传输过程【网络常识10】_哔哩哔哩_bilibili 常识都看看 》Ref&#xff1a; 1. 这个写的嘎嘎好&#xff0c;解释了为啥4层7层5层&#xff0c;还有数据包封装的问题:数据包在网络中的传输过程详解_数据包传输_张孟浩_jay的博客…...

Acwing.875 快速幂

题目 给定n组ai , bi, pi&#xff0c;对于每组数据&#xff0c;求出akimod pi的值。 输入格式 第一行包含整数n。 接下来n行&#xff0c;每行包含三个整数ai , bi,pi。输出格式 对于每组数据&#xff0c;输出一个结果&#xff0c;表示aibimod pi的值。 每个结果占一行。 数…...

【决策树-鸢尾花分类】

决策树算法简介 决策树是一种基于树状结构的分类与回归算法。它通过对数据集进行递归分割&#xff0c;将样本划分为多个类别或者回归值。决策树算法的核心思想是通过构建树来对数据进行划分&#xff0c;从而实现对未知样本的预测。 决策树的构建过程 决策树的构建过程包括以…...

类与对象(中--构造函数)

类与对象&#xff08;中--构造函数&#xff09; 1、构造函数的特性2、默认构造函数3、编译器自动生成的默认构造函数&#xff08;无参的&#xff09;&#xff08;当我们不写构造函数时&#xff09;3.1 编译器自动生成的默认构造函数只对 自定义类型的成员变量 起作用&#xff0…...

Makefile学习1

文章目录 Makefile学习1Makefile简介Makefile重要性Makefile内容1) 显式规则2) 隐晦规则3) 变量的定义4) 文件指示5) 注释 Makefile规则规则默认目标多目标多规则目标伪目标 Makefile目标依赖头文件依赖自动生成头文件依赖关系 Makefile命令Makefile变量变量定义和使用赋值立即…...

城市内涝监测预警系统,科学“智治”应对灾害

近日&#xff0c;台风“杜苏芮”以摧枯拉朽之势给我国东南沿海地区带来狂风骤雨&#xff0c;福建的三个国家气象观测站日降水量突破历史极值。之后&#xff0c;“杜苏芮”一路北上。中央气象台预报称&#xff0c;7月29日至8月1日&#xff0c;北京、天津、河北、山东西部、河南北…...

切片[::-1]解析列表list表示的“非负整数加1”

列表数位表示非负整数&#xff0c;熟练操作“满十进位”。 (本笔记适合熟练操作Python列表list的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅…...

Mac下certificate verify failed: unable to get local issuer certificate

出现这个问题&#xff0c;可以安装证书 在finder中查找 Install Certificates.command找到后双击&#xff0c;或者使用其他终端打开 安装完即可...

Django项目启动错误

uwsgi项目启动错误信息如下Did you install mysqlclient?Command pkg-config --exists mysqlclient returned non-zero exit status 1Command pkg-config --exists mariadb returned non-zero exit status 1.Traceback (most recent call last):File "/home/dream21th/co…...

Vue2 第十二节 Vue组件化编程 (二)

1. VueComponent 2. 单文件组件 一. VueComponent 组件本质上是一个名为VueComponent的构造函数&#xff0c;不是程序员定义的&#xff0c;是Vue.extend生成的只需要写<school/>或者<school><school/>&#xff0c;Vue解析时&#xff0c;会帮我们创建schoo…...

pycharm 远程连接服务器并且debug, 支持torch.distributed.launch debug

未经允许&#xff0c;本文不得转载&#xff0c;vx&#xff1a;837007389 文章目录 step1&#xff1a;下载专业版本的pycharmstep2 配置自动同步文件夹&#xff0c;即远程的工程文件和本地同步2.1 Tools -> Deployment -> configuration2.2 设置同步文件夹2.3 同步服务器…...

SAP ABAP 基础语法超详细

1&#xff0e;表声明 Tables: 表名[,表名]. 声明多个表时可用逗号分隔当你声明了一个数据表的同时&#xff0c;系统也同时自动生成了一个和数据表同名的结构&#xff0c;结构的变量集等于数据表里面的字段。 2&#xff0e;定义变量 Data: v1[(l)] [type t] [decimals d] [v…...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...