ThinkPHP5模型关联(多对多关联)

关联定义

多对多关联不像一对一和一对多关联,它还要多建一个中间表用来处理多对多的关联,例如:

#城市
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(区域)模型:

<?php

namespace app\demo\model;
use think\Model;

class Area  extends Model   //全国区域表
{
    public function city(){
        //belongsToMany('城市模型','中间表名','外键名','外键名');
        return $this->belongsToMany("Area",'city_area','aid','cid');
    }
}

中间表模型可以不需要建立

 

关联查询

我们可以通过下面的方式获取关联数据

        $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);