🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] #### 关联定义 我们以用户和档案的一对一关联为例,在User模型类中添加关联定义方法,然后在方法中调用hasOne方法即可: ~~~ <?php namespace app\index\model; use think\Model; class User extends Model { // 开启自动写入时间戳 protected $autoWriteTimestamp = true; // 定义自动完成的属性 protected $insert = ['status' => 1]; // 定义关联方法 public function profile() { // 用户HAS ONE档案关联 return $this->hasOne('Profile'); } } ~~~ hasOne方法有5个参数,依次分别是: ~~~ hasOne('关联模型名','关联外键','主键','别名定义','join类型') ~~~ 默认的外键是:当前模型名_id,主键则是自动获取,如果你的表设计符合这一规范的话,只需要设置关联的模型名即可. 通常关联模型和当前模型都是相同的命名空间,如果关联模型在不同的命名空间,需要指定完整的类名,例如: ~~~ // 关联admin模块下面的模型对象 return $this->hasOne('\app\admin\Profile'); ~~~ 要进行模型的关联操作,我们必须同时定义好关联模型,Profile模型定义如下: ~~~ <?php namespace app\index\model; use think\Model; class Profile extends Model { protected $type = [ 'birthday' => 'timestamp:Y-m-d', ]; } ~~~ 可以看到Profile模型中并没有定义关联方法。如果你的关联操作都是基于User模型的话,Profile模型中并不需要定义关联方法。 如果你需要基于Profile模型来进行关联操作,则需要在Profile模型中定义对应的BELONGS_TO关联,如下: ~~~ <?php namespace app\index\model; use think\Model; class Profile extends Model { protected $type = [ 'birthday' => 'timestamp:Y-m-d', ]; public function user() { // 档案 BELONGS TO 关联用户 return $this->belongsTo('User'); } } ~~~ belongsTo方法和hasOne一样,也有5个参数: ~~~ belongsTo('关联模型名','关联外键','关联模型主键','别名定义','join类型') ~~~ #### 关联写入 首先来看下如何进行关联数据的写入,创建User控制器的add操作方法如下: ~~~ <?php namespace app\index\controller; use app\index\model\Profile; use app\index\model\User as UserModel; class User { // 关联新增数据 public function add() { $user = new UserModel; $user->name = 'thinkphp'; $user->password = '123456'; $user->nickname = '流年'; if ($user->save()) { // 写入关联数据 $profile = new Profile; $profile->truename = '刘晨'; $profile->birthday = '1977-03-05'; $profile->address = '中国上海'; $profile->email = 'thinkphp@qq.com'; $user->profile()->save($profile); return '用户新增成功'; } else { return $user->getError(); } } } ~~~ 关联模型的写入调用了关联方法profile(),该方法返回的是一个Relation对象,执行save方法会自动传入当前模型User的主键作为关联键值,所以不需要手动传入Profile模型的user_id属性。 save方法也可以直接使用数组而不是Profile对象,例如: ~~~ <?php namespace app\index\controller; use app\index\model\Profile; use app\index\model\User as UserModel; class User { // 关联新增数据 public function add() { $user = new UserModel; $user->name = 'thinkphp'; $user->password = '123456'; $user->nickname = '流年'; if ($user->save()) { // 写入关联数据 $profile['truename'] = '刘晨'; $profile['birthday'] = '1977-03-05'; $profile['address'] = '中国上海'; $profile['email'] = 'thinkphp@qq.com'; $user->profile()->save($profile); return '用户[ ' . $user->name . ' ]新增成功'; } else { return $user->getError(); } } } ~~~ #### 关联查询 ~~~ 一对一的关联查询很简单,直接把关联对象当成属性来用即可,例如: public function read($id) { $user = UserModel::get($id); echo $user->name . '<br/>'; echo $user->nickname . '<br/>'; echo $user->profile->truename . '<br/>'; echo $user->profile->email . '<br/>'; } ~~~ 以上关联查询的时候,只有在获取关联对象($user->profile)的时候才会进行实际的关联查询,缺点是会可能进行多次查询,但可以使用预载入查询来提高查询性能,对于一对一关联来说,只需要进行一次查询即可获取关联对象数据,例如: ~~~ public function read($id) { $user = UserModel::get($id,'profile'); echo $user->name . '<br/>'; echo $user->nickname . '<br/>'; echo $user->profile->truename . '<br/>'; echo $user->profile->email . '<br/>'; } ~~~ get方法使用第二个参数就表示进行关联预载入查询。 #### 关联更新 一对一的关联更新如下: ~~~ public function update($id) { $user = UserModel::get($id); $user->name = 'framework'; if ($user->save()) { // 更新关联数据 $user->profile->email = 'liu21st@gmail.com'; $user->profile->save(); return '用户[ ' . $user->name . ' ]更新成功'; } else { return $user->getError(); } } ~~~ #### 关联删除 关联删除代码如下: ~~~ public function delete($id) { $user = UserModel::get($id); if ($user->delete()) { // 删除关联数据 $user->profile->delete(); return '用户[ ' . $user->name . ' ]删除成功'; } else { return $user->getError(); } } ~~~