# 多表关联
数据表之间经常会互相进行关联。例如,一篇博客文章可能会有多条评论,或是一张订单可能对应一个下单客户。HDPHP模型让管理和处理这些关联变得很容易,同时也支持多种类型的关联。
[TOC]
## 一对一
「一对一」关联是一个非常基本的关联关系。举个例子,一个 User 模型会关联一个 Phone 模型。为了定义这种关联关系,我们需要在 User 模型中写一个 phone 方法。且 phone 方法应该调用 hasOne 方法并返回其结果:
```
namespace system\model;
use houdunwang\model\Model;
class User extends Model{
//获取与用户关联的电话号码
public function phone()
{
return $this->hasOne(App\Phone::class);
}
}
```
#### 参数说明
模型会假设对应关联的外键名称是基于模型名称的。在这个例子里,它会自动假设 Phone 模型拥有 user_id 外键。如果你想要重写这个约定,则可以传入第二个参数到 hasOne 方法里。
```
return $this->hasOne('App\Phone', 'user_id');
```
此外 Model假设外键会和上层模型的 id 字段(或者自定义的 $primaryKey)的值相匹配。换句话说,Model 会寻找用户的 id 字段与 Phone 模型的 user_id 字段的值相同的纪录。如果你想让关联使用 id 以外的值,则可以传递第三个参数至 hasOne 方法来指定你自定义的键:
```
return $this->hasOne('App\Phone', 'user_id', 'id');
```
#### 动态属性
第一个传到 hasOne 方法里的参数是关联模型的类名。一旦定义好两者之间关联,我们就可以通过使用模型获取关联表数据了。
```
$phone = User::find(1)->phone;
```
## 一对多
多对多就是指一第表含有另一张表的多条记录,比如说一个用户会有多条新闻。
下面是一对多的定义示例,在用户模型中定义与新闻的关联关系。
多对多与一对多一样,每一个参数是关联的模型类,第二个参数是foreign_key(文章表中记录的用户表的主键),第三个参数是local_key(用户表主键)。
```
namespace system\model;
use houdunwang\model\Model;
class User extends Model{
//获取与用户关联的电话号码
public function news()
{
return $this->hasMany(App\News::class);
}
}
```
比如用户表的主键字段为id,文章表与用户表关联字段为user_id,我们可以使用以下形式。
```
$this->hasMany(App\News::class,'user_id','id');
```
#### 参数说明
第三个参数不添加时,系统会自动提取user表主键字段
第二个参数不添加时,系统自动使用 “user_+user表主键字段” 的形式
#### 动态属性
以下是使用模型定义的方法的示例。
```
User::find(1)->news;
```
## 一对多(反向关联)
现在我们已经能访问到所有用户的文章,让我们来接着定义一个通过文章访问所属用户的关联。若要定义相对于 hasMany 的关联,可在子级模型定义一个叫做 belongsTo 方法的关联函数:
```
namespace system\model;
use houdunwang\model\Model;
class News extends Model{
public function user()
{
return $this->belongsTo(App\User::class);
}
}
```
#### 参数说明
belongsTo 可以定义三个参数,第一个参数是关联的类,第二个参数是文章表中保存用户表的主键字段,第三个参数是用户表的主键字段。
比如用户表的主键字段为id,文章表与用户表关联字段为user_id,我们可以使用以下形式。
```
$this->belongsTo(App\User::class,'user_id','id');
```
第三个参数不添加时,系统会自动提取user表主键字段
第二个参数不添加时,系统自动使用 “user_+user表主键字段” 的形式
#### 动态属性
一旦关联被定义之后,则可以通过 user 的「动态属性」来获取 News 模型相对应的 User 模型:
```
$news = ModelJoinNews::find(2);
$news->user->username;
```
## 多对多
「多对多」关联要稍微比 hasOne 及 hasMany 关联复杂。比如,一个用户属于多个用户组,每个组又可以有多个用户,这就是多对多关联。这种情况下我们需要一张中间表来连接这个关联关系。即三张表,user用户表 group 用户组表 user_group中间表。
```
namespace system\model;
use houdunwang\model\Model;
class User extends Model{
public function group()
{
return $this->belongsToMany(ModelJoinGroup::class,'user_group','user_id','group_id');
}
}
```
#### 参数说明
1. 关联表模型类,以上例来讲就是 Group模型
2. 中间表的表名,添加时使用user_group
3. 中间表中保存的当前模型表的主键(用户表主键),不添加时使用当前表名_id,以上例来讲就是 user_id
4. 中间表中保存的关联表的主键(用户组表主键),不添加时使用关联表名_id, 以上例来讲就是 group_id
#### 关联使用
```
$user = ModelJoinUser::find(1);
$group = $user->group;
foreach($group as $g){
echo $g->name;
}
```
- 文档已经迁移到后盾人
- 介绍
- 框架特性
- 开发规范
- 许可协议
- 作者向军
- 安装框架
- 更新框架
- 基础
- 入口文件
- 应用配置
- 优雅链接
- 目录结构
- 系统常量
- 自动加载
- 应用密钥
- 系统函数
- CSRF保护
- 依赖注入
- 跨域访问
- 配置
- 配置文件
- 基本功能
- 扩展配置
- c 函数
- 控制器
- 定义声明
- 基本使用
- 相关函数
- 响应消息
- 路由
- 基础知识
- 基础路由
- 路由参数
- 参数检测
- 依赖注入
- 控制器
- 分组路由
- RESTful
- 别名路由
- 数据
- 配置相关
- 核心操作
- 查询构造器
- 日志记录
- 分页处理
- 事务处理
- 函数相关
- 数据库
- 数据迁移
- 数据填充
- 模型
- 定义模型
- 模型动作
- 模型验证
- 自动完成
- 自动过滤
- 字段保护
- 数据填充
- 多表关联
- 分页处理
- 仓库
- 数据仓库
- 查询规则
- 视图
- 基础知识
- 模板配置
- 模板文件
- 分配数据
- 系统标签
- 扩展标签
- 缓存模板
- 模板继承
- 视图函数
- widget
- vue组件
- 中间件
- 中间件
- 缓存
- 基本操作
- 文件缓存
- 数据表缓存
- 服务
- 服务容器
- 定制服务
- 相关函数
- 请求
- 基本使用
- 请求扩展
- 测试
- 基础知识
- 基本使用
- HTTP测试
- 调试
- 调试模式
- 日志管理
- 组件
- 多语言
- 响应处理
- Cookie
- Session
- 验证码
- XML
- 自动验证
- 文件处理
- 压缩解压
- RBAC
- 数组增强
- 分页管理
- 图像处理
- 生成静态
- 加密解密
- 字符串
- 数据集合
- 工具服务
- 目录操作
- 邮件发送
- CURL
- QQ登录
- 数据备份
- 购物车
- 日志处理
- 命令组件
- 二维码
- 后盾云
- 日期处理
- 阿里
- 支付宝
- 阿里云直播
- 阿里云短信
- 阿里云邮件
- 阿里云OSS
- SOCKET
- 启动与关闭
- 前端
- 微信