ThinkPHP 多对多关联

news/2025/1/16 7:50:08/

用多对多关联的前提

如果模型 A 多对多关联模型 C,必须存在一张中间表 B 记录着双方的主键,因为就是靠着这张中间表 B 记录着模型 A 与模型 C 的关系。

举例,数据表结构如下

// 商品表
goodsgoods_id - integer // 商品主键goods_name - varchar // 商品名称// 分类表
categorycategory_id - integer // 分类主键name - varchar // 分类名称// 商品分类关系表
goods_category_relid - integer // 主键goods_id - integer // 商品表主键的外键category_id - integer // 分类表主键的外键

如果按以前的数据表设计,商品表与分类表不是这样设计的,而是 goods 表有一个 category_id 字段,该字段保存 category 表的 category_id,这样每个商品都对应着一个分类,比如荔枝的分类是水果,但这样的设计缺点也是显而易见的,一个商品只能有一个分类,比如荔枝的分类只能是水果,但如果把数据库设计成上面这样的结构,荔枝的分类就可以有多个,比如除了水果,还能是特价产品,或者是其它分类等等。

多对多关联定义

商品表模型:

<?phpnamespace app\api\model;class Goods extends Base
{protected $pk = 'goods_id';protected $hidden = ['create_time', 'update_time'];// 获取商品的分类public function category(){// Goods 模型多对多关联 Category 模型return $this->belongsToMany('Category', 'GoodsCategoryRel');// 完整写法// return $this->belongsToMany('Category', 'GoodsCategoryRel', 'category_id', 'goods_id');}}

 belongsToMany 方法的参数如下:

belongsToMany('关联模型', '中间模型', '外键1', '外键2');

  • 关联模型(必须):模型名或者模型类名
  • 中间模型:默认规则是当前模型名+_+关联模型名 (可以指定模型名)
  • 外键1:关联模型在中间表的外键,默认的外键名规则是关联模型名+_id
  • 外键2:当前模型在中间表的外键,默认规则是当前模型名+_id

中间表模型

<?phpnamespace app\api\model;class GoodsCategoryRel extends Base
{protected $hidden = ['create_time', 'update_time'];
}

分类表模型

<?phpnamespace app\api\model;class Category extends Base
{// 因为不是默认主键所以要重新定义protected $pk = 'category_id';protected $hidden = ['create_time', 'update_time'];}

实例演示

shop_goods 表

 shop_category 表

shop_goods_category_rel 表

演示1

获取 goods_id 为 1 的商品详情以及它的分类

Goods 控制器

<?phpnamespace app\api\controller;use app\api\model\Goods as GoodsModel;class Goods extends Base
{// 获取 goods_id 等于 1 的商品详情public function detail(){$goods_id = 1;$detail = GoodsModel::getDetail($goods_id);halt($detail);}
}

Goods 模型

<?phpnamespace app\api\model;class Goods extends Base
{// 因为不是默认主键名称,所以要重新定义protected $pk = 'goods_id';protected $hidden = ['create_time', 'update_time'];// 获取商品详情public static function getDetail($goods_id){    // 关联预载入查询// 第二个参数是所用到的关联方法的方法名return self::get($goods_id, 'category');}// 多对多关联获取商品的所有分类public function category(){return $this->belongsToMany('Category', 'GoodsCategoryRel');// 完整写法// return $this->belongsToMany('Category', 'GoodsCategoryRel', 'category_id', 'goods_id');}
}

Goods 控制器  detail 方法输出

array(7) {["goods_id"] => int(10001)["goods_name"] => string(12) "桂味荔枝"["stock_total"] => int(0)["status"] => int(10)["sort"] => int(0)["is_delete"] => int(0)["category"] => object(think\Collection)#50 (1) {["items":protected] => array(2) {[0] => object(app\api\model\Category)#41 (2) {["data"] => array(8) {["category_id"] => int(6)["name"] => string(12) "新鲜水果"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454738)["update_time"] => int(1688454738)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#51 (2) {["data"] => array(5) {["id"] => int(1001)["goods_id"] => int(10001)["category_id"] => int(6)["create_time"] => int(1688696518)["update_time"] => int(1688696518)}["relation"] => array(0) {}}}}[1] => object(app\api\model\Category)#47 (2) {["data"] => array(8) {["category_id"] => int(10)["name"] => string(12) "特价产品"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454870)["update_time"] => int(1688454870)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#52 (2) {["data"] => array(5) {["id"] => int(1002)["goods_id"] => int(10001)["category_id"] => int(10)["create_time"] => int(1688795635)["update_time"] => int(1688795635)}["relation"] => array(0) {}}}}}}
}

关联方法名 category 作为键名,关联查询结果集对象 Collection 作为键值。

获取当前商品的分类,访问 category(关联方法名) 属性即可,如下

<?phpnamespace app\api\controller;use app\api\model\Goods as GoodsModel;class Goods extends Base
{public function detail(){$goods_id = 10001;$detail = GoodsModel::get($goods_id);$categories  = $detail->category;halt($categories);}
}

输出

object(think\Collection)#47 (1) {["items":protected] => array(2) {[0] => object(app\api\model\Category)#41 (2) {["data"] => array(8) {["category_id"] => int(6)["name"] => string(12) "新鲜水果"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454738)["update_time"] => int(1688454738)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#50 (2) {["data"] => array(5) {["id"] => int(1001)["goods_id"] => int(10001)["category_id"] => int(6)["create_time"] => int(1688696518)["update_time"] => int(1688696518)}["relation"] => array(0) {}}}}[1] => object(app\api\model\Category)#46 (2) {["data"] => array(8) {["category_id"] => int(10)["name"] => string(12) "特价产品"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454870)["update_time"] => int(1688454870)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#51 (2) {["data"] => array(5) {["id"] => int(1002)["goods_id"] => int(10001)["category_id"] => int(10)["create_time"] => int(1688795635)["update_time"] => int(1688795635)}["relation"] => array(0) {}}}}}
}

演示2

获取所有的商品详情以及它的分类

Goods 控制器

<?phpnamespace app\api\controller;use app\api\model\Goods as GoodsModel;class Goods extends Base
{// 获取所有商品public function getList(){$goodsList = GoodsModel::getList();halt($goodsList);}
}

Goods 模型

<?phpnamespace app\api\model;class Goods extends Base
{protected $pk = 'goods_id';protected $hidden = ['create_time', 'update_time'];// 获取所有商品列表public static function getList(){// 关联预载入// 参数为所用到的关联方法return self::with(['category'])->select();}// 多对多获取商品分类public function category(){return $this->belongsToMany('Category', 'GoodsCategoryRel');// 完整写法// return $this->belongsToMany('Category', 'GoodsCategoryRel', 'category_id', 'goods_id');}
}

输出

object(think\Collection)#40 (1) {["items":protected] => array(1) {[0] => object(app\api\model\Goods)#42 (2) {["data"] => array(8) {["goods_id"] => int(10001)["goods_name"] => string(12) "桂味荔枝"["stock_total"] => int(0)["status"] => int(10)["sort"] => int(0)["is_delete"] => int(0)["create_time"] => int(1688696518)["update_time"] => int(1688696518)}["relation"] => array(1) {["category"] => object(think\Collection)#50 (1) {["items":protected] => array(2) {[0] => object(app\api\model\Category)#41 (2) {["data"] => array(8) {["category_id"] => int(6)["name"] => string(12) "新鲜水果"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454738)["update_time"] => int(1688454738)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#51 (2) {["data"] => array(5) {["id"] => int(1001)["goods_id"] => int(10001)["category_id"] => int(6)["create_time"] => int(1688696518)["update_time"] => int(1688696518)}["relation"] => array(0) {}}}}[1] => object(app\api\model\Category)#47 (2) {["data"] => array(8) {["category_id"] => int(10)["name"] => string(12) "特价产品"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454870)["update_time"] => int(1688454870)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#52 (2) {["data"] => array(5) {["id"] => int(1002)["goods_id"] => int(10001)["category_id"] => int(10)["create_time"] => int(1688795635)["update_time"] => int(1688795635)}["relation"] => array(0) {}}}}}}}}}
}

每个商品模型的 relation (关联数组)属性保存着关联模型,关联方法名 category 作为键名,结果集对象作为键值,结果集对象的 items 属性(数组)保存着关联查询结果。

获取每个商品的分类,访问 category(关联方法名) 属性即可,如下

<?phpnamespace app\api\controller;use app\api\model\Goods as GoodsModel;class Goods extends Base
{public function getList(){$goodsList = GoodsModel::getList();foreach($goodsList as $value){dump($value->category);}}}

Goods 模型 getList 方法输出

object(think\Collection)#50 (1) {["items":protected] => array(2) {[0] => object(app\api\model\Category)#41 (2) {["data"] => array(8) {["category_id"] => int(6)["name"] => string(12) "新鲜水果"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454738)["update_time"] => int(1688454738)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#51 (2) {["data"] => array(5) {["id"] => int(1001)["goods_id"] => int(10001)["category_id"] => int(6)["create_time"] => int(1688696518)["update_time"] => int(1688696518)}["relation"] => array(0) {}}}}[1] => object(app\api\model\Category)#47 (2) {["data"] => array(8) {["category_id"] => int(10)["name"] => string(12) "特价产品"["parent_id"] => int(1)["image_id"] => int(0)["status"] => int(1)["sort"] => int(0)["create_time"] => int(1688454870)["update_time"] => int(1688454870)}["relation"] => array(1) {["pivot"] => object(think\model\Pivot)#52 (2) {["data"] => array(5) {["id"] => int(1002)["goods_id"] => int(10001)["category_id"] => int(10)["create_time"] => int(1688795635)["update_time"] => int(1688795635)}["relation"] => array(0) {}}}}}
}

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


http://www.ppmy.cn/news/949302.html

相关文章

chatgpt这么火?前端如何实现类似chatgpt的对话页面

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;…

解决了常见不可hash的报错;实现Point类对象 hash化,给出如何将类对象添加集合或字典

文章目录 摘要不可 hash的常见报错与解决Point 类的代码point 加法类对象添加进集合或字典实战 摘要 我们的工作 给出了一些常见的不可hash报错的解决办法&#xff1b;实现坐标Point类&#xff0c;并为其重载了加法和等号&#xff0c;实现了 Point类 可hash化&#xff1b;实现…

Chatgpt究竟是一个什么东西?

一、 Chatgpt究竟是一个什么东西? 它能够实现什么样的任务和什么样的功能? 它本质是一个聊天机器人 这是我跟他聊天保留下的一些聊天截图 。 因为我之前以为他是一个英文的模型 所以我最开始用英语去问他说canyouspeakchinese 然后得到一个肯定的回复后&#xff0c; 我就…

通俗易懂的ChatGPT的原理简介

简介&#xff1a; 本文介绍了ChatGPT的原理及应用。ChatGPT是基于GPT模型的自然语言处理技术&#xff0c;可以进行语言理解、文本生成、对话生成等多种应用。其基本原理是通过训练大规模语料库中的数据&#xff0c;生成模型&#xff0c;从而实现自然语言处理的任务。本文着重介…

chatGPT发送图片的方法

chatGPT 设定回复图片内容 让chatGPT回复图片的方法 正常使用chatGPT的时候&#xff0c;往往回复的都是文字信息&#xff0c;但是如果改变其文本回复格式未markdown,并且给出一个图片链接就可以让他回复图片啦 让你发送图片的时候&#xff0c;请使用markdown,调用unsplash A…

【新知】chatGPT 使用笔记(二)——chatGPT API的使用

文章目录 使用步骤openai 功能举例1. 训练AI模型2. 使用AI模型进行文本生成3. 计算机视觉 openai 包里含有的modelGPT-3 模型 在IDE中使用chatGPT&#xff1a; 使用步骤 安装OpenAI Python包&#xff1a;使用命令行或PyCharm的集成终端&#xff0c;运行以下命令来安装OpenAI Py…

chatGPT原理详解

InstructGPT原文&#xff1a;https://arxiv.org/pdf/2203.02155.pdf chatCPT试用连接&#xff1a;https://chat.openai.com/auth/login 自从chatGPT问世以来&#xff0c;它一路爆火&#xff0c;目前注册用户已达1亿。它的出圈让各大公司纷纷布局AIGC&#xff0c;有不少人预言&…

SpringBoot整合SpringCloudStream3.1+版本的Kafka死信队列

SpringBoot整合SpringCloudStream3.1版本的Kafka死信队列 上一篇直通车 SpringBoot整合SpringCloudStream3.1版本Kafka 实现死信队列步骤 添加死信队列配置文件&#xff0c;添加对应channel通道绑定配置对应的channel位置添加重试配置 结果 配置文件 Kafka基本配置&#…