ThinkPHP的模型关联(多对多关联)
关联定义
多对多关联不像一对一和一对多关联,它还要多建一个中间表用来处理多对多的关联,例如:
#城市 create table city ( c_id int primary key AUTO_INCREMENT comment "编号", c_name varchar(255) comment '城市名称' ) #区域(别名) create table area ( a_id int primary key AUTO_INCREMENT comment "编号", a_name varchar(255) comment '区域名称' ) #中间表(枢纽表) create table city_area ( id int primary key AUTO_INCREMENT comment "编号", aid int comment '区域外键', cid int comment '城市外键' )
一个区域(别名)有多座城市,一座城市有多个区域(别名),例如:广州即属于一线城市,也是珠三角地区,同时它还叫“羊城”;而珠三角地区包括的城市有广州、佛山、肇庆、深圳、东莞、惠州等。
下面使用belongsToMany关联中间表,city(城市)模型:
<?php namespace app\demo\model; use think\Model; class City extends Model //城市表 { public function area(){ //belongsToMany('区域模型','中间表名','外键名','外键名'); return $this->belongsToMany('Area','city_area','aid','cid'); } }
注:belongsToMany后面两个一定要对应中间表外键的顺序
area(区域)模型:
class Area extends Model //全国区域表 { public function city(){ //belongsToMany('城市模型','中间表名','外键名','外键名'); return $this->belongsToMany("City",'city_area','aid','cid'); } public function city(){ //belongsToMany('城市模型','中间表名'); 这种也一样 return $this->belongsToMany("City",'city_area'); } }
中间表模型可以不需要建立
关联查询
我们可以通过下面的方式获取关联数据
$city = City::get(1); foreach($city->area as $role){ // 获取城市id为1的所有区域名称 dump($role->a_name); }
如果要获取中间表数据,可以使用
$city = City::get(1); foreach($city->area as $role){ // 获取中间表数据 print_r($role->pivot); }
关联新增
//关联单条新增 $city = City::get(1); //增加关联数据 会自动写入中间表数据 $city->area()->save(['a_name'=>'珠三角地区']); //批量新增 $city->area()->saveAll([ ['a_name'=>'一线城市'], ['a_name'=>'羊城'], ]);
只新增中间表数据,可以使用
//方法一:添加中间表数据 $city = City::get(1); //条件查询,找出珠三角地区 $area = Area::getByAName("珠三角地区"); //使用attach方法增加中间表的数据 $city->area()->attach($area);//新增数据:城市的id为1,区域为珠三角地区的id*/ //方法二:,效果等同方法一 $city = City::get(1); $city->area()->attach(2);//新增数据:城市的id为1,区域为2
下面是新增中间表方法二执行的SQL语句:
INSERT INTO `city_area` (`cid` , `aid`) VALUES (1 , 2)
关联删除
只删除中间表数据,但不删关联模型的数据
//方法一: $city = City::get(1); $area = Area::getByAName("珠三角地区"); //关联删除数据,但不删关联模型的数据 $city->area()->detach($area); //方法二 $city = City::get(1); //DELETE FROM `city_area` WHERE `cid` = 1 AND `aid` = 1 $city->area()->detach(1); //批量删除 $city->area()->detach([1]);
删除中间表方法二执行的SQL:
DELETE FROM `city_area` WHERE `cid` = 1 AND `aid` = 1
如果有必要,也可以删除中间表的数据同时删除关联模型
$city = City::get(1); $area = Area::getByAName("羊城"); //这里不光删除中间表,也删除羊城 $city->area()->detach($area,true);