目录 搜索
基础 安装ThinkPHP5.1 开发规范 目录结构 配置基础 架构 路由 控制器 请求 架构总览 入口文件 URL访问 模块设计 命名空间 容器和依赖注入 Facade 钩子和行为 路由定义 变量规则 路由地址 闭包支持 路由参数 跨域请求 注解路由 路由分组 MISS路由 资源路由 快捷路由 路由别名 路由绑定 域名路由 URL生成 控制器定义 前置操作 跳转和重定向 空操作和空控制器 分层控制器 资源控制器 请求对象 输入变量 请求类型 HTTP头信息 伪静态 参数绑定 请求缓存 响应 响应输出 响应参数 重定向 数据库 模型 视图 连接数据库 查询数据 添加数据 更新数据 删除数据 查询表达式 链式操作 where table alias field strict limit page order group having join union distinct lock cache comment fetchSql force partition failException sequence 聚合查询 时间查询 高级查询 视图查询 JSON字段 子查询 原生查询 查询事件 事务操作 监听SQL 存储过程 数据集 分布式数据库 定义 新增 更新 删除 查询 JSON数据字段 获取器 修改器 自动时间戳 只读字段 软删除 类型转换 数据完成 查询范围 模型输出 事件 关联 一对一关联 一对多关联 远程一对多 多对多关联 多态关联 关联预载入 关联统计 关联输出 视图渲染 视图赋值 视图过滤 模板引擎 模板 变量输出 使用函数 运算符 原样输出 模板注释 模板布局 模板继承 包含文件 输出替换 标签库 内置标签 循环标签 比较标签 条件判断 资源文件加载 标签嵌套 原生PHP 定义标签 错误和日志 异常处理 日志处理 调试 验证 杂项 命令行 扩展库 安全和性能 附录 调试模式 性能调试 SQL调试 变量调试 远程调试 验证器 验证规则 错误信息 验证场景 路由验证 内置规则 独立验证 静态调用 表单令牌 缓存 Session Cookie 多语言 分页 上传 自动生成目录结构 创建类库文件 生成类库映射文件 清除缓存文件 生成配置缓存文件 生成数据表字段缓存 生成路由映射缓存 自定义指令 验证码 图像处理 Time 数据库迁移工具 Workerman MongoDb 单元测试 安全建议 优化建议 助手函数 升级指导 更新日志
文字

一对一关联


版本新增功能
5.1.2增加selfRelation方法定义当前关联为自关联

关联定义

定义一对一关联,例如,一个用户都有一个个人资料,我们定义User模型如下:

<?php
namespace app\index\model;

use think\Model;

class User extends Model
{
    public function profile()
    {
        return $this->hasOne('Profile');
    }
}

hasOne方法的参数包括:

hasOne('关联模型','外键','主键');

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

  • 关联模型(必须):关联的模型名或者类名

  • 外键:默认的外键规则是当前模型名(不含命名空间,下同)+_id ,例如user_id

  • 主键:当前模型主键,默认会自动获取也可以指定传入

一对一关联定义的时候还支持额外的方法,包括:


方法名描述
setEagerlyType定义关联查询方式,0 - JOIN查询 1 - IN查询(默认)
bind绑定关联属性到父模型
joinTypeJOIN方式查询的JOIN方式,默认为INNER
selfRelation定义当前关联为自关联

如果使用了JOIN方式的关联查询方式,你可以在额外的查询条件中使用关联方法名作为表的别名。

关联查询

定义好关联之后,就可以使用下面的方法获取关联数据:

$user = User::get(1);
// 输出Profile关联模型的email属性
echo $user->profile->email;

默认情况下, 我们使用的是user_id 作为外键关联,如果不是的话则需要在关联定义的时候指定,例如:

<?php
namespace app\index\model;

use think\Model;

class User extends Model 
{
    public function profile()
    {
        return $this->hasOne('Profile','uid');
    }
}

有一点需要注意的是,关联方法的命名规范是驼峰法,而关联属性则一般是小写+下划线的方式,系统在获取的时候会自动转换对应,读取user_profile关联属性则对应的关联方法应该是userProfile。

关联保存

$user = User::get(1);
// 如果还没有关联数据 则进行新增
$user->profile()->save(['email' => 'thinkphp']);

系统会自动把当前模型的主键传入Profile模型。

和新增一样使用save方法进行更新关联数据。

$user = User::get(1);
$user->profile->email = 'thinkphp';
$user->profile->save();
// 或者
$user->profile->save(['email' => 'thinkphp']);

定义相对关联

我们可以在Profile模型中定义一个相对的关联关系,例如:

<?php
namespace app\index\model;

use think\Model;

class Profile extends Model 
{
    public function user()
    {
        return $this->belongsTo('User');
    }
}

belongsTo的参数包括:

belongsTo('关联模型','外键','关联主键');

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

  • 关联模型(必须):模型名或者模型类名

  • 外键:当前模型外键,默认的外键名规则是关联模型名+_id

  • 关联主键:关联模型主键,一般会自动获取也可以指定传入

默认的关联外键是user_id,如果不是,需要在第二个参数定义

<?php
namespace app\index\model;
use think\Model;
class Profile extends Model 
{
    public function user()
    {
        return $this->belongsTo('User','uid');
    }
}

我们就可以根据档案资料来获取用户模型的信息

$profile = Profile::get(1);
// 输出User关联模型的属性
echo $profile->user->account;

绑定属性到父模型

可以在定义关联的时候使用bind方法绑定属性到父模型,例如:

<?php
namespace app\index\model;

use think\Model;

class User extends Model 
{
    public function profile()
    {
        return $this->hasOne('Profile','uid')->bind('nickname,email');
    }
}

或者使用数组的方式指定绑定属性别名

<?php
namespace app\index\model;

use think\Model;

class User extends Model 
{
    public function profile()
    {
        return $this->hasOne('Profile','uid')->bind([
                'email',
                'truename'  => 'nickname',
                'profile_id'  => 'id',
            ]);
    }
}

然后使用关联预载入查询的时候,可以使用

$user = User::get(1,'profile');
// 输出Profile关联模型的email属性
echo $user->email;
echo $user->profile_id;

绑定关联模型的属性支持读取器。

如果不是预载入查询,请使用模型的appendRelationAttr方法追加属性。

关联自动写入

我们可以使用together方法更方便的进行关联自动写入操作。

写入

$blog = new Blog;
$blog->name = 'thinkphp';
$blog->title = 'ThinkPHP5关联实例';
$content = new Content;
$content->data = '实例内容';
$blog->content = $content;
$blog->together('content')->save();

如果绑定了子模型的属性到当前模型,可以用数组指定子模型的属性

$blog = new Blog;
$blog->name = 'thinkphp';
$blog->title = 'ThinkPHP5关联实例';
$blog->content = '实例内容';
// title和content是子模型的属性
$blog->together(['content'=>['title','content']])->save();

更新

// 查询
$blog = Blog::get(1);
$blog->title = '更改标题';
$blog->content->data = '更新内容';
// 更新当前模型及关联模型
$blog->together('content')->save();

删除

// 查询
$blog = Blog::get(1,'content');
// 删除当前及关联模型
$blog->together('content')->delete();

如果不想这么麻烦每次调用together方法,也可以直接在模型类中定义relationWrite属性,但必须是数组方式。不过考虑到模型的独立操作的可能性,并不建议。


上一篇: 下一篇: