tp5的关联

发布于 2019-04-13  392 次阅读


关联

[TOC]


一对多

关联

在User的model中创建关联Comment的model:


1
2
3
    public function comm(){
        return $this->hasMany('comment','uid','id');   //model model的字段 本model的字段
    }

在控制器中**使用**关联(属性/方法)

读取

1
2
3
4
5
6
7
8
9
        $user = User::get(1);
        //属性 //是一个comment对象数组
//        print_r($user->comm);
//        foreach($user->comm as $comm){
//            echo $comm['content'];
//        }
        //方法  返回一个Relation的model(HasMany类)  
        $sel = $user->comm()->where('content','不知道')->select();
        echo $sel;
1
$user->comm()->find()

1
$comm = $user->comm()->getByContent('不知道')

返回Comment类

1
$user->comm()

1
$user->comm()->where('content','哈哈哈')

返回HasMany类(Relation)

1
$user->comm()->where('content','哈哈哈')->select()

返回数组

1
$user->comm

返回comment对象数组

查询id为1的user表的同时查询uid为1的comment表


1
$user = User::get(1,'comm');         //返回User类

返回的User model如下:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
    "id": 1,
    "name": "用户名",
    "email": "157465655@163.com",
    "birthday": 1998,
    "comm": [
        {
            "content": "哈哈哈",
            "uid": 1
        },
        {
            "content": "可还行",
            "uid": 1
        },
        {
            "content": "不知道",
            "uid": 1
        },
        {
            "content": "不知道",
            "uid": 1
        },
        {
            "content": "哈哈哈",
            "uid": 1
        }
    ]
}

除此之外,还有model的静态方法has(聚合查询):


1
2
3
4
5
$user = User::has('comm')->select();//如果有评论就将数组赋给$user   relation
//带条件的
$user = User::has('comm','>=',2)->select();//如果有大于等于2条评论就将数组赋给$user  relation op count
//hasWhere
$user = User::hasWhere('comm',['content'=>'哈哈哈'])->select();

执行这个方法之后的sql日志:


1
2
3
4
5
[ sql ] [ SQL ] SELECT `User`.* FROM `user` `User` INNER JOIN `comment` `Comment` ON `User`.`id`=`Comment`.`uid` GROUP BY `Comment`.`uid` HAVING count(*)>=1 [ RunTime:0.001734s ]

[ sql ] [ SQL ] SELECT `User`.* FROM `user` `User` INNER JOIN `comment` `Comment` ON `User`.`id`=`Comment`.`uid` GROUP BY `Comment`.`uid` HAVING count(*)>=2 [ RunTime:0.000704s ]

[ sql ] [ SQL ] SELECT `User`.* FROM `user` `User` INNER JOIN `comment` `Comment` ON `User`.`id`=`Comment`.`uid` WHERE  `Comment`.`content` = '哈哈哈' GROUP BY `User`.`id` [ RunTime:0.002099s ]
写入

因为getByContent()返回的时Comment类所以写入可以直接使用getByContent('字段1')->字段2=值的方式设置

使用User::get(1,'comm')返回的User类也可以使用where()->update([‘字段’=>值])设置

删除等操作以此类推

一对一

users model对应car model


1
2
3
    public function car(){
        return $this->hasOne('car','uid','id');             //model  model关联字段   本model字段
    }

由于是一对一

1
$user->car

是一个car对象

照样

1
$user->car()

是一个HasOne对象(Relation)

同理

1
$user->car()->find()

是一个car对象

设置car

1
2
3
$c = $user->car()->find();
$c->brand = "zhp";
$c->save();
新增user和car:

1
2
3
4
5
6
7
8
9
10
11
12
$user = new User;
$user->name = 'maidd';
$user->email = '155@163.com';
$user->birthday = '2019/01/01';
if($user->save()){
$car['brand'] = '奔驰';          
$car['plate_number'] = 1124576;
$user->car()->save($car);          //设置car         car的uid自动生成
return 'nb';
}else{
return $user->getError();
}

删除同理。

多对多

原理:

数据库中存在三张表:需要对应的两张表和一张中间表(只有两个字段(分别是前两个表的关联id),建议将其命名为model名+‘_id’,字段存入的值时那两个model的主键(id)的值)

对应的model里有两个关联的Shippingarea和Region model

首先关联model:

Shippingarea model里


1
2
3
public function region(){
    return $this->belongsToMany('Region','area_region','shipping_id','region_id'); //model 带前缀的数据表 中间表的字段1 字段2(顺序不要换)当后面两个参数为空时,会以model名+‘_id’来传入
}

同理Region model里:


1
2
3
public function shippingarea(){
    return $this->belongsToMany('Shippingarea','area_region','shipping_id','region_id'); //model 带前缀的数据表 中间表的字段1 字段2(顺序不要换)当后面两个参数为空时,会以model名+‘_id’来传入
}
新增关联

然后在控制器里面操作:


1
2
$region = Region::getByName('北京');
$region->shippingarea()->save(['name'=> '中国首都']);
新增多个关联

1
2
3
4
5
$region = Region::get(1);
$region->shippingarea()->saveAll([
    ['name'=> '中国首都'],
    ['name' => '全国一线城市'],
]);
关联两个已经存在的数据

1
2
3
$region = Region::get(2);
$shipping = Shippingarea::get(2);
$region->shippingarea()->attach($shipping);   //反过来也可以
删除两个已经存在的数据的关联

1
2
3
$region = Region::get(2);
$shipping = Shippingarea::get(2);
$region->shippingarea()->detach($shipping,true);//true表示删除中间表数据的同时删除$shipping的数据

先这样,以后再改吧