Thinkphp 实现多对多

在做实验的时候,要求写一个考试管理系统,这时候就必不可少的要涉及到实体之间的关系,而其中比较难处理的就是多对多关系。

问题描述

两个实体,教师和课程,关系多对多。要实现在新建教师的时候能为教师添加多个课程,可编辑,删除时删除相应的关系。

问题解决

关联定义

首先,我们肯定要先定义教师和课程的多对多。在教师的模型定义如下:

1
2
3
4
5
class User extends Model {
public function courses() {
return $this->belongsToMany('Course');
}
}

这样就定义了多对多关系,但是还没有结束,还需要去数据库中建立一张中间表teacher_course,然后定义表中字段。到此,关系维护结束。

关联添加

因为我们在添加关系的时候,课程和教师都已经存好了,所以这时候我们只用操作中间表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$post = Request::instance()->post();
// 获取要保存的关联课程
$courseIds = $post['course_id'];
$Teacher = new Teacher();
$Teacher->name = $post['name'];
$Teacher->sex = $post['sex'];
$Teacher->work_number = $post['work_number'];
$Teacher->password = $post['password'];
if ($Teacher->save()) {
// 在教师添加成功后修改中间表
$Teacher->courses()->attach($courseIds);
return $this->success('保存成功!', 'index');
} else {
return $this->error('保存失败!');
}

获取从V层传过来的数据,包括要保存的所有课程id,然后当教师保存成功后再修改中间表,将教师和课程的id对应的存入中间表中。(attach()这个函数只会操作中间表,另外两个数据表不会被改变。)

关联删除

同样的关联删除只能操作中间表。

1
2
3
4
5
6
7
8
9
10
11
12
...
if ($Teacher->delete()) {
// 获取所有的关联课程,依次删除
$courses = $Teacher->courses;
foreach ($courses as $course) {
$Teacher->courses()->detach($course->id);
}
return $this->success('删除成功!', url('index'));
} else {
return $this->error('删除失败!');
}
...

遍历获取所有的与删除的教师关联的课程,然后遍历删除。(同样,detach()函数也只会操作中间表)

关联编辑

编辑稍微复杂一点,需要先将原来的关联关系删除,然后再保存新的关系。也就是将上面的添加和删除合在一起了。这样一分析就简单了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$post = Request::instance()->post();
$courseIds = $post['course_id'];
...
if ($Teacher->save()) {
// 删除原来的关系
$courses = $Teacher->courses;
foreach ($courses as $course) {
$Teacher->courses()->detach($course->id);
}
// 加入新的关系
$Teacher->courses()->attach($courseIds);
return $this->success('保存成功!', url('index'));
} else {
return $this->error('保存失败!');
}

与添加一样,先获取V层传过来的id数组。然后在教师对象修改完后,去除原来的教师课程关系,然后将新的id存进去。

总结

最近用惯了java,在维护实体关系的时候都是由hibernate替我们自动维护的,只需要写几个注解和配置项。一方面我们感叹hibernate的强大;但是另一方面,我们有了实现功能的思想,发现自己去实现的时候也并不困难。


官方参考:
https://www.kancloud.cn/manual/thinkphp5/142359

坚持原创技术分享,您的支持将鼓励我继续创作!