对于关联方式,系统提供了9种方案,具体如下:
上面的例子,我们采用了一对一的关联模型,它还有相对的反向关联;
下面给出一个例子:
class Profile extends Model {
public function user() {
return $this->belongsTo(User::class);
}
}
$profile = ProfileModel::find(1);
return $profile->user->email;
一对一关联查询
一张 tp_user表,主键为:id;附属表:tp_profile,建立两个字段:user_id和 hobby,外键是user_id。
hasOne
hasOne模式,适合主表关联附表,具体设置方式如下:
hasOne('关联模型',['外键','主键']);
关联模型(必须):关联的模型名或者类名
外键:默认的外键规则是当前模型名(不含命名空间,下同)+_id ,例如 user_id
主键:当前模型主键,默认会自动获取也可以指定传入
return $this->hasOne(Profile::class,'user_id', 'id');
创建User模型和Profile模型,均为空模型;User模型端,需要关联Profile,具体方式如下:
class User extends Model
{
public function profile() {
//hasOne表示一对一关联,参数一表示附表,参数二外键,默认user_id
return $this->hasOne(Profile::class,'user_id');
} }
创建一个控制器用于测试输出:Grade.php:
$user = UserModel::find(21);
return json($user->profile);
return $user->profile->hobby;
使用 save()方法,可以设置关联修改,通过主表修改附表字段的值;
$user = UserModel::find(19);
$user->profile->save(['hobby'=>'酷爱小姐姐']);
->profile属性方式可以修改数据,->profile()方法方式可以新增数据;
$user->profile()->save(['hobby'=>'不喜欢吃青椒']);
belongsTo
belongsTo模式,适合附表关联主表,具体设置方式如下:
belongsTo('关联模型',['外键','关联主键']);
return $this->belongsTo(Profile::class,'user_id', 'id');
关联模型(必须):模型名或者模型类名
外键:当前模型外键,默认的外键名规则是关联模型名+_id
关联主键:关联模型主键,一般会自动获取也可以指定传入
对于 belongsTo()的查询方案如下:
$profile = ProfileModel::find(1);
return $profile->user->email;
使用 hasOne()也能模拟 belongsTo()来进行查询;
//参数一表示的是User模型类的profile方法,而非Profile模型类
$user = UserModel::hasWhere('profile', ['id'=>2])->find();
return json($user);
//采用闭包,这里是两张表操作,会导致id识别模糊,需要指明表
$user = UserModel::hasWhere('profile', function ($query) {
$query->where('profile.id', 2);
})->select();
return json($user);
一对多关联查询
hasMany模式
hasMany模式,适合主表关联附表,实现一对多查询,具体设置方式如下:
hasMany('关联模型',['外键','主键']);
return $this->hasMany(Profile::class,'user_id', 'id');
关联模型(必须):模型名或者模型类名
外键:关联模型外键,默认的外键名规则是当前模型名+_id
主键:当前模型主键,一般会自动获取也可以指定传入
使用->profile()方法模式,可以进一步进行数据的筛选;
$user->profile()->where('id', '>', 10)->select();
$user->profile->where('id', '>', 10)
使用 has()方法,查询关联附表的主表内容,比如大于等于 2条的主表记录;
UserModel::has('profile', '>=', 2)->select();
使用 hasWhere()方法,查询关联附表筛选后记录,比如兴趣审核通过的主表记录;
UserModel::hasWhere('profile', ['status'=>1])->select();
使用 save()和 saveAll()进行关联新增和批量关联新增,方法如下:
$user = UserModel::find(19);
$user->profile()->save(['hobby'=>'测试喜好', 'status'=>1]);
$user->profile()->saveAll([
['hobby'=>'测试喜好', 'status'=>1],
['hobby'=>'测试喜好', 'status'=>1]
]);
使用 together()方法,可以删除主表内容时,将附表关联的内容全部删除;
$user = UserModel::with('profile')->find(227);
$user->together(['profile'])->delete();
多对多关联查询
首先,我们来看多对多关系的三张表,具体如下:
tp_user:用户表;tp_role:角色表;tp_access:中间表;access表包含了 user和 role表的关联 id,多对多模式。
在 User.php的模型中,设置多对多关联,方法如下:
public function roles()
{
return $this->belongsToMany(Role::class, Access::class);
}
在 roles方法中,belongsToMany为多对多关联,具体参数如下:
belongsToMany('关联模型','中间表',['外键','关联键']);
$this->belongsToMany(Role::class, Access::class, 'role_id', 'user_id');
role.php和 access.php创建一个空模型即可,无须创建任何。注意,注意:Role继承 Model即可,而中间表需要继承 Pivot;在 user.php中,创建 many()方法,用于测试,查询方式如下:
public function many()
{
//得到一个用户:蜡笔小新
$user = UserModel::find(21);
//获取这个用户的所有角色
$roles = $user->roles;
//输出这个角色所具有的权限
return json($roles);
}
当我们要给一个用户创建一个角色时,用到多对多关联新增;而关联新增后,不但会给 tp_role新增一条数据,也会给 tp_access新增一条;
$user->roles()->save(['type'=>'测试管理员']);
$user->roles()->saveAll([[...],[...]]);
一般来说,上面的这种新增方式,用于初始化角色比较合适,也就是说,各种权限的角色,并不需要再新增了,都是初始制定好的。我们真正需要就是通过用户表新增到中间表关联即可;
$user->roles()->save(1);
或:
$user->roles()->save(Role::find(1)); $user->roles()->saveAll([1,2,3]);
或:
$user->roles()->attach(1);
$user->roles()->attach(2, ['details'=>'测试详情']);
除了新增,还有直接删除中间表数据的方法:
$user->roles()->detach(2);