关联模型,顾名思义,就是将表与表之间进行关联和对象化,即合并两张表的数据,然后进行增删改查的操作。
比如以下两张表,tp_user表,主键为:id;附属表:tp_profile,建立两个字段:user_id和hobby,外键是user_id;
tp_user
tp_profile
一般主表存放一些经常存取的信息,附表存放一些不常用的额外信息,从而节约资源。
现在我们需要根据主表查找到附表的一些信息。
第二步就是创建User模型和Profile模型,均为空模型;
model/User.php
正向关联:User模型端(主),需要关联Profile(附),具体方式如下: 然后新建控制器controller/Grade.php 当然主类中也可以改名,但是相应的控制器中获取的也要改(建议名称都保持一致): classUserextendsModel{//与表名一一对应publicfunctionprofileAAA(){//hasOne表示一对一关联,参数一表示附表,参数二外键,默认user_idreturn$this->hasOne(Profile::class);}}echo$user->profileAAA->hobby;关于外键: 对于关联方式,系统提供了9种方案,具体如下: 一对一关联反向操作 在model/profile.php中 namespaceapp\model;usethink\Model;classProfileextendsModel{publicfunctionuser(){return$this->belongsTo(User::class,'user_id');}}在控制器中 namespaceapp\controller;useapp\model\UserasUserModel;useapp\model\ProfileasProfileModel;classGrade{publicfunctionindex(){$profile=ProfileModel::find(1);echo$profile->user->username;}}正反向关联也就是关联关系和相对的关联关系 hasOne模式,适合主表关联附表 hasOne('关联模型',['外键','主键']);return$this->hasOne(Profile::class,'user_id','id');关联模型(必须):关联的模型名或者类名 外键:默认的外键规则是当前模型名(不含命名空间,下同)+_id,例如user_id 主键:当前模型主键,默认会自动获取也可以指定传入 关联修改 比如现在需要通过主表user中的id找到关联的附表对应的行并修改其内容 在控制器中: $user=UserModel::find(19);$user->profile->save(['hobby'=>'酷爱科比']);关联新增 通过主表id找到关联附表中对应行如果没有关联行就新增 $user=UserModel::find(19);$user->profile()->save(['hobby'=>'酷爱橘艾莱娜']);这时候我们会发现,如果附表中原本存在关联行的情况下,这样执行依然会在附表中新增一条,这就会变成一对多了 所以就需要在附表中先判断,user_id存在不存在,否则会直接新增一条。 belongsTo模式,适合附表关联主表,具体设置方式如下(反向操作): belongsTo('关联模型',['外键','关联主键']);return$this->belongsTo(Profile::class,'user_id','id');关联模型(必须):模型名或者模型类名 外键:当前模型外键,默认的外键名规则是关联模型名+_id关联 主键:关联模型主键,一般会自动获取也可以指定传入 反向关联 使用hasOne()也能模拟belongsTo()来进行查询,即hasOne也能实现反向查询,这样就不需要belongs方法了: 参数一表示的是User模型类的profile方法,而非Profile模型类 //id=1代表的是z找到附表的id=1的行$user=UserModel::hasWhere('profile',['id'=>1])->find();return$user;通过profile模型找到附表id=1的行找出来然后找到对应的主表的id=19的值 采用闭包,这里是两张表操作,会导致id识别模糊,需要指明表 使用闭包好处就是可以自定义SQL查询语句,实现更多的操作。 $user=UserModel::hasWhere('profile',function($query){$query->where('id','=',1);})->find();return$user;一对多关联查询hasManyhasMany模式,适合主表关联附表,实现一对多查询 hasMany('关联模型',['外键','主键']);return$this->hasMany(Profile::class,'user_id','id');关联模型(必须):模型名或者模型类名 外键:关联模型外键,默认的外键名规则是当前模型名+_id 主键:当前模型主键,一般会自动获取也可以指定传入 比如在模型中 namespaceapp\model;usethink\Model;classUserextendsModel{//一对多publicfunctionprofile(){return$this->hasMany(Profile::class,'user_id');}}控制器中 $user=UserModel::find(19);returnjson($user->profile);最终会返回如下形式: [{id:1,user_id:19,hobby:"酷爱科比",status:1},{id:37,user_id:19,hobby:"不喜欢吃青椒",status:1},{id:46,user_id:19,hobby:"酷爱橘艾莱娜",status:0}]所以一对一跟一对多在查询方面的区别就是,一对多最终返回的是一个数组,返回的是多条;而一对一只会返回一条; 使用->profile()方法模式,可以进一步进行数据的筛选 $user=UserModel::find(19);returnjson($user->profile()->select());注意,这里如果仅仅使用$user->profile()是不会有任何结果返回的,必须配合->select() $user->profile()->select()效果等价于$user->profile使用方法可以对结果进行链式查询,增加条件 returnjson($user->profile()->where('id','>=',10)->select());使用has()方法,查询关联附表的主表内容(从附表查询主表的内容),比如大于等于2条的主表记录; UserModel::has('profile','>=',2)->select();意思是:要在附表中查找,有两条以上主表关联的数据,一条的就不搜出来 附表: 主表 $user=UserModel::find(19);returnjson($user->has('profile','>=',2)->select());最终返回的是查询到的主表信息,就是主表中id=19的行在附表中有两条关联数据。 [{id:19,username:"蜡笔小新",password:"123"}]使用hasWhere()方法,查询关联附表筛选后记录,比如兴趣审核通过的主表记录 UserModel::hasWhere('profile',['status'=>1])->select();使用save()和saveAll()进行关联新增和批量关联新增 给附表中,新增一条/多条,并指定附表中user_id=19 新增一条 $user->profile()->save(['hobby'=>'测试喜好','status'=>1]);新增多条 $user=UserModel::find(19);$user->profile()->saveAll([['hobby'=>'ceshi1','status'=>1],['hobby'=>'ceshi2','status'=>1]]);关联删除 比如要在删除主表中的信息时候,也要链带将附表中的关联信息也一起删掉 使用together()方法,可以删除主表内容时,将附表关联的内容全部删除; //关联删除$user=UserModel::with('profile')->find(331);//注意together参数是一个数组,是可以关联多个附表,就是将多个附表中user_id=xx的都删除$user->together(['profile'])->delete();注意,这里如果->find(331),而id=331在主表中不存在的话,系统会报错。