关联定义

多对多关联不像一对一和一对多关联,它还要多建一个中间表用来处理多对多的关联,例如:

#城市
create table city
(
c_id int primary key AUTO_INCREMENT comment "编号",
c_name varchar(255) comment '城市名称'
) #区域(别名)
create table area
(
a_id int primary key AUTO_INCREMENT comment "编号",
a_name varchar(255) comment '区域名称'
) #中间表(枢纽表)
create table city_area
(
id int primary key AUTO_INCREMENT comment "编号",
aid int comment '区域外键',
cid int comment '城市外键'
)

一个区域(别名)有多座城市,一座城市有多个区域(别名),例如:广州即属于一线城市,也是珠三角地区,同时它还叫“羊城”;而珠三角地区包括的城市有广州、佛山、肇庆、深圳、东莞、惠州等。

下面使用belongsToMany关联中间表,city(城市)模型:

<?php

namespace app\demo\model;
use think\Model; class City extends Model //城市表
{
public function area(){
//belongsToMany('区域模型','中间表名','外键名','外键名');
return $this->belongsToMany('Area','city_area','aid','cid');
}
}

注:belongsToMany后面两个一定要对应中间表外键的顺序

area(区域)模型:

<?php

namespace app\demo\model;
use think\Model; class Area extends Model //全国区域表
{
public function city(){
//belongsToMany('城市模型','中间表名','外键名','外键名');
return $this->belongsToMany("Area",'city_area','aid','cid');
}
}

中间表模型可以不需要建立

关联查询

我们可以通过下面的方式获取关联数据

        $city = City::get(1);
foreach($city->area as $role){
// 获取城市id为1的所有区域名称
dump($role->a_name);
}

如果要获取中间表数据,可以使用

        $city = City::get(1);
foreach($city->area as $role){
// 获取中间表数据
print_r($role->pivot);
}

关联新增

        //关联单条新增
$city = City::get(1);
//增加关联数据 会自动写入中间表数据
$city->area()->save(['a_name'=>'珠三角地区']);
//批量新增
$city->area()->saveAll([
['a_name'=>'一线城市'],
['a_name'=>'羊城'],
]);

只新增中间表数据,可以使用

        //方法一:添加中间表数据
$city = City::get(1);
//条件查询,找出珠三角地区
$area = Area::getByAName("珠三角地区");
//使用attach方法增加中间表的数据
$city->area()->attach($area);//新增数据:城市的id为1,区域为珠三角地区的id*/ //方法二:,效果等同方法一
$city = City::get(1);
$city->area()->attach(2);//新增数据:城市的id为1,区域为2

下面是新增中间表方法二执行的SQL语句:

INSERT INTO `city_area` (`cid` , `aid`) VALUES (1 , 2)

关联删除

只删除中间表数据,但不删关联模型的数据

        //方法一:
$city = City::get(1);
$area = Area::getByAName("珠三角地区");
//关联删除数据,但不删关联模型的数据
$city->area()->detach($area); //方法二
$city = City::get(1);
//DELETE FROM `city_area` WHERE `cid` = 1 AND `aid` = 1
$city->area()->detach(1); //批量删除
$city->area()->detach([1]);

删除中间表方法二执行的SQL:

DELETE FROM `city_area` WHERE `cid` = 1 AND `aid` = 1

如果有必要,也可以删除中间表的数据同时删除关联模型

        $city = City::get(1);
$area = Area::getByAName("羊城");
//这里不光删除中间表,也删除羊城
$city->area()->detach($area,true);

ThinkPHP5——模型关联(多对多关联)的更多相关文章

  1. thinkphp5 模型表关联

    student 表 外键 grade_idgrade 表主键 id在 模型中student表关联方法public function Grade(){ return $this->hasOne(' ...

  2. ThinkPHP5——模型关联(一对一关联)

    定义 定义一对一关联使用了hasOne,hasOne方法的参数包括: hasOne('关联模型名','外键名','主键名',['模型别名定义'],'join类型'); 下面定义一个用户表,公司给每个用 ...

  3. 《Entity Framework 6 Recipes》中文翻译系列 (30) ------ 第六章 继承与建模高级应用之多对多关联

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第六章  继承与建模高级应用 现在,你应该对实体框架中基本的建模有了一定的了解,本章 ...

  4. (Hibernate进阶)Hibernate映射——多对多关联映射(八)

    多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数 ...

  5. 深入理解 Laravel Eloquent(三)——模型间关系(关联)

    Eloquent是什么 Eloquent 是一个 ORM,全称为 Object Relational Mapping,翻译为 "对象关系映射"(如果只把它当成 Database A ...

  6. 05.Hibernate多对多关联

        前言:本文讲解使用Hibernate映射多对多关联关系,并使用多种方式映射多对多关联. 1.数据库表的多对多关系     本文根据学生信息表(tb_student)和教师信息表(tb_teac ...

  7. Mybatis 一对一、一对多、多对多关联之级联添加

    示例项目:MIPO_CRM 一.一对一关联 示例:订单与销售机会 描述:在业务员与客户的联系人的联系记录中可以生成一条销售机会,而此条销售机会可生成一条订单,两者呈一对一关联. 1.表设计 oppor ...

  8. 【SSH系列】Hibernate映射 -- 多对多关联映射

         映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论 ...

  9. 【SSH进阶之路】Hibernate映射——多对多关联映射(八)

    上篇博文[SSH进阶之路]Hibernate映射——一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接 ...

随机推荐

  1. [2018-01-12] python 当天学习笔记

    Python模块 Python欧快(Moudule),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句. 模块让你能够有逻辑地组织你的Python代码段. 把相关的代 ...

  2. CSPS模拟 58

    爆炸 没算内存见祖宗 为什么偏偏这次卡内存我没算 T1 HashMap各种水 T2 智障背包!但是卡内存! T3 Dashspeed 考试用点分治+线段树水到了80 实际上是个没见过的套路题 在之前的 ...

  3. 如何编译安装Linux内核

    操作系统环境 VMware workstation15 Pro ubuntu18.04 LTS 待编译内核5.3.10版本 内核下载地址 kernel.org 环境配置 在正式编译前需要安装部分软件. ...

  4. php查询字符串的函数

    /* 查找一个字符串在另一个字符串的第一次出现,并返回其余部分(strstr别名) */ var_dump(strchr("hello world hello", "wo ...

  5. 超简单解决linux音乐播放器乱码问题

    问题 中文MP3的tag信息有些因为采用了GBK编码, 导致linux下的大多播放器(Rhythmbox, Audacious)无法正确识别而显示乱码. 如下图Audacious的乱码情况. 网上的常 ...

  6. 创建基于OData的Web API - Knowledge Builder API, Part II:Project Setup

    本篇为Part II:Project Setup 查看第一篇<Part I:  Business Scenario> 第一步,准备步骤. 准备步骤一,下载.NET Core 2.2 SDK ...

  7. C++中对C的扩展学习新增语法——强枚举

    枚举类型 C++中对枚举的加强: 1.C++不允许非枚举值赋值给枚举类型,不允许其他枚举类型的值赋值给当前枚举类型,而C语言中是允许的. 2.枚举值具有外层作用域,容易造成名字冲突. 3.不同类型的枚 ...

  8. springMVC-MyBatis-Mysql 环境下, 返回时间格式不是指定格式

    在数据库中的时间是: 比如: 2018-04-06:12;23:34. 但是mybatis查询出来以后是下面的格式. {"updatedTime":{"date" ...

  9. asp.net core 自定义 Policy 替换 AllowAnonymous 的行为

    asp.net core 自定义 Policy 替换 AllowAnonymous 的行为 Intro 最近对我们的服务进行了改造,原本内部服务在内部可以匿名调用,现在增加了限制,通过 identit ...

  10. NetCore基于EasyNetQ的高级API使用RabbitMq

    一.消息队列 消息队列作为分布式系统中的重要组件,常用的有MSMQ,RabbitMq,Kafa,ActiveMQ,RocketMQ.至于各种消息队列的优缺点比较,在这里就不做扩展了,网上资源很多. 更 ...