# 多对多关联
## 关联定义
例如,我们的用户和角色就是一种多对多的关系,我们在`User`模型定义如下:
~~~
<?php
namespace app\model;
use think\Model;
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class, 'UserRole', 'role_id', 'user_id');
}
}
~~~
`belongsToMany`方法的参数如下:
> ### belongsToMany('关联模型','中间表','外键','关联键');
* **关联模型**(必须):关联模型类名,Role 或者 Role::class
* **中间表模型**:默认的表名是当前模型名+`_`+关联模型名 (可自定义)
* **外键**:中间表的当前模型外键,默认的外键名规则是关联模型名+`_id`
* **关联键**:中间表的当前模型关联键名,默认规则是当前模型名+`_id`
中间表名无需添加表前缀,并支持定义中间表模型,例如:
~~~
public function roles()
{
return $this->belongsToMany(Role::class, Access::class);
}
~~~
中间表模型类必须继承`think\model\Pivot`,例如:
~~~
<?php
namespace app\model;
use think\model\Pivot;
class Access extends Pivot
{
protected $autoWriteTimestamp = 'datetime';
}
~~~
中间表模型的基类`Pivot`默认关闭了时间戳自动写入,上面的中间表模型则开启了时间戳字段自动写入。
## 关联查询
我们可以通过下面的方式获取关联数据
~~~
$user = UserModel::find(1);
pr($user->toArray());
// 获取用户的所有角色
$roles = [];
foreach ($user->roles as $role) {
$roles[] = $role->name;
// 获取中间表模型
pr($role->pivot->toArray());
}
pr($roles);
~~~
## 关联新增
~~~
$user = User::find(1);
// 给用户增加管理员权限 会自动写入角色表和中间表数据
$user->roles()->save(['name'=>'管理员']);
// 批量授权
$user->roles()->saveAll([
['name'=>'管理员'],
['name'=>'操作员'],
]);
~~~
只新增中间表数据(角色已经提前创建完成),可以使用
~~~
$user = User::find(1);
// 仅增加管理员权限(假设管理员的角色ID是1)
$user->roles()->save(1);
// 或者
$role = Role::find(1);
$user->roles()->save($role);
// 批量增加关联数据
$user->roles()->saveAll([1,2,3]);
~~~
单独更新中间表数据,可以使用:
~~~
$user = User::find(1);
// 增加关联的中间表数据
$user->roles()->attach(1);
// 传入中间表的额外属性
$user->roles()->attach(1,['remark'=>'test']);
// 删除中间表数据
$user->roles()->detach([1,2,3]);
~~~
> `attach`方法的返回值是一个`Pivot`对象实例,如果是附加多个关联数据,则返回`Pivot`对象实例的数组。
其他方法
public function save($data, array $pivot = \[\])
public function saveAll(iterable $dataSet, array $pivot = \[\], bool $samePivot = false)
public function attach($data, array $pivot = \[\])
public function attached($data)
public function detach($data = null, bool $relationDel = false): int
public function sync(array $ids, bool $detaching = true): array
~~~
public function update() {
// $data = [1,2];
$data = [1=>['memo' => 'read'], 2=>['memo' => 'write']];
$user = UserModel::find(1);
//$user->roles()->sync([1,3]);
$user->roles()->sync($data);
}
~~~
- 搭建ThinkPHP6的开发环境
- 配置ThinkPHP6
- 必要的基础知识(basic)
- MVC开发模式
- 控制器(controller)
- 数据库(database)
- 模型(model)
- 模型关联(relation)
- 视图(view)
- Session
- Cookie
- 缓存(cache)
- 上传(upload)
- 验证器(validate)
- 验证码(captcha)
- 命令行(command)
- 服务器部署(deploy)
- 数据备份(backup)
- 数据同步(synchronization)
- 订阅服务(subscribe)
- PHP 易混淆知识点
- 助手函数
- MySQL规范
- Redis 规范
- office插件 phpoffice
- 拼音插件 pinyin
- 日期插件 datetime
- 消息插件 amqp
- 产品部署环境的搭建
- PDF 等杂项处理
- 文件上传
- 常用扩展
- flc/dysms
- 使用示例 ①
- 使用示例 ②
- qiniu/php-sdk
- 简介
- 使用示例
- 使用示例 2 ②
- liliuwei/thinkphp-jump
- 扩展介绍
- 下载扩展
- 使用方法
- topthink/think-captcha
- 安装扩展
- 验证码显示
- 更换验证码
- 验证码校验
- 验证码配置
- 自定义验证码
- phpoffice/phpspreadsheet
- 数据写入表格
- 读取表格数据
- topthink/think-queue
- 安装
- 自定义函数
- 任务类
- 带有日志的任务类