想了想我还是觉得在写一篇关于多对多的文档吧,因为我看了官方的文档写的不够细,不好理解。我自己也花了时间去看人家的文档还有自己又做了一些测试才知道怎么用的现在把我做测试的所有过程分享给大家。
数据库表与数据
就从数据库表开始啦,因为这样可能会更利于大家去理解。大家都知道数据库多对多关系都是需要三张表来完成的,一张主表,一张关联表,还有一张中间表。比如我们这里主表是学生表关联课程表。因为一个学生可以学多们课程,一门课程可以有多个学生来上课所以需要有一个中间表把他们关联起来。现在我就把今天需要做测试的几张表都贴出来,也方便大家在有不明白的时候可以拿来做测试。
下面这张是学生表:
/*学生表*/
DROP TABLE IF EXISTS `pwn_student`;
CREATE TABLE pwn_student (
id INT AUTO_INCREMENT,
name VARCHAR(30),
age INT ,
class VARCHAR(50),
address VARCHAR(100),
PRIMARY KEY(id)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
/* 表数据 */
insert into pwn_student(name,age,`class`,address) values('学生A',15,'二班','a路2号');
insert into pwn_student(name,age,`class`,address) values('学生B',16,'二班','a路1号');
insert into pwn_student(name,age,`class`,address) values('学生C',15,'二班','B路1号');
中间表:
/*学生课程关联表*/
DROP TABLE IF EXISTS `pwn_Stu_Cour`;
CREATE TABLE pwn_Stu_Cour(
id INT AUTO_INCREMENT,
stu_id INT ,
cour_id INT,
PRIMARY KEY(id)
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
/*表数据*/
insert into pwn_Stu_cour(stu_id,cour_id) values(1,1);
insert into pwn_Stu_cour(stu_id,cour_id) values(2,2);
insert into pwn_Stu_cour(stu_id,cour_id) values(3,3);
insert into pwn_Stu_cour(stu_id,cour_id) values(1,1);
insert into pwn_Stu_cour(stu_id,cour_id) values(2,2);
insert into pwn_Stu_cour(stu_id,cour_id) values(3,3);
insert into pwn_Stu_cour(stu_id,cour_id) values(1,1);
insert into pwn_Stu_cour(stu_id,cour_id) values(2,2);
insert into pwn_Stu_cour(stu_id,cour_id) values(3,3);
insert into pwn_Stu_cour(stu_id,cour_id) values(1,1);
insert into pwn_Stu_cour(stu_id,cour_id) values(2,2);
insert into pwn_Stu_cour(stu_id,cour_id) values(3,3);
学生课程表
/*学生课程表*/
DROP TABLE IF EXISTS `pwn_Course`;
CREATE TABLE `pwn_Course`(
`id` INT AUTO_INCREMENT NOT NULL,
`name` VARCHAR(150) NOT NULL DEFAULT '',
PRIMARY KEY(id)
)ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;
/*表数据*/
insert into `pwn_course`(name) values('数学');
insert into `pwn_course`(name) values('语文');
insert into `pwn_course`(name) values('物理');
insert into `pwn_course`(name) values('化学');
insert into `pwn_course`(name) values('生物');
insert into `pwn_course`(name) values('英语');
如果有对数据库多对多关系有不明白的大家可以到网上去搜索一下因为今天主要讲的是TP5的关联模型,如果mysql也讲的话就内容太多了。
创建模型
在模型开始创建之前先给大家介绍一个方法,是thinkphp5关联模型多对多中需要使用到的方法 belongsToMany 方法。
belongsToMany方法的参数如下:
belongsToMany(‘关联模型名’,’中间表名’,’外键名’,’当前模型关联键名’,[‘模型别名定义’]);
关联模型名:
是指当前模型需要关联的其他模型,比如我们的当前模型是Student 摸行,去关联 Course 模型,那关联模型就需要填course。
中间表名:
这个就不用说了,就是中间表名不用写前缀。
外键名:
是中间表 pwn_Stu_Cour 关联 course 表的外键id。
当前模型关联键名:
是中间表 pwn_Stu_Cour 关联 student 表的关联键名。
现在一切都准备好了之后接下来就进入今天的主题,创建tp模型。一般情况下一张表需要对应创建一个模型,但是多对多的关系里中间表的模型可以省略掉。也就是说我们只要创建学生表模型 Student 和课程表模型就可以了。
下面是Student模型
<?php
namespace app\index\model;
use think\Model;
class Student extends Model{
public function Course(){
//cour_id是关联中间表的关联course表的外键id,而stu_id也是中间表关联学生表的外键id
//两个id都是中间表关联其他表的外键id
//这个大家应该一看就知道都是中间表的id,因为在`pwn_student` 学生表和`pwn_Course`课程表里没有这两个字段。
return $this->belongsToMany('course','stu_cour','cour_id','stu_id');
}
}
?>
这个模型上面 belongsToMany() 方法的参数什么相信大家都已经知道了吧,如果不知道的话回头到上面去看一下。
下面这个是 Course 模型
<?php
namespace app\index\model;
use think\Model;
class Course extends Model{
function Student(){
// return $this->belongsTo('Admin','aid','id');
// return $this->belongsToMany('student','stu_cour','cour_id','stu_id');
}
}
?>
这个Course模型可以是空的不写任何方法但是不能没有不然会报错。
控制器调用:
关联新增
控制器调用模型和其他调用方法一样也是先用命名空间把他引入控制器然后调用
use app\index\model\Student;
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\Student;
class index extends Controller
{
/**
* @param string $name
*/
public function index($name='name')
{
//这的意思是从 pwn_student 学生表的name字段中取出'学生A'的信息
$student=Student::getByName('学生A');
//给关联表 pwn_course 新增一条 name 数据
$res= $student->Course()->save(['name'=>'地理']);
if($res){
echo "新增成功";
}
}
}
?>
这样在 pwn_course 表里新增一条数在中间表里也会自动生成有对应关联id的数据,只要在模型中把中间表关联的id位置写对。
这是 pwn_course 表新增之前的数据:
这下面是中间表新增前的数据:
好现在刷新执行以下控制器看看效果,如果你的浏览器里显示成功并且没有任何报错就表示成功:
这是我的执行结果,我们看到它已经新增成功了。接下来看看数据库是不是也是成功了。
从图上可以看出我们新增的数据已经添加到了数据表里了。表示在这张表上面是没有问题的已经把数据添加上去了,但是我们还有一张把学生表和课程表关联起来很重要的中间表是否也添加成功了呢?接下来让我们到 pwn_Stu_Cour 中间表去看一下。
我们看到数据不仅是添加进去了!而且id都已经对号入座说明我们已经成功。
新增中间表数据
比如我们想给‘学生A’新增一门语文课。这个时候我们就需要添加中间表来完成新增‘学生A’的课程。还有一个是我们需要用模型 Course 来获取课程信息所以这个时候 Course 表就不能是空的了。他需要关联 Student 模型,关联的方法和 Student 一样。
下面是 Course 模型:
<?php
namespace app\index\model;
use think\Model;
class Course extends Model{
function Student(){
// return $this->belongsTo('Admin','aid','id');
return $this->belongsToMany('student','stu_cour','stu_id','cour_id');
}
}
?>
因为所有的方法参数都是和 Studen 模型是一样的所以我这里就不多介绍了。
下面是控制器方法:
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\Student;
use app\index\model\Course;
class index extends Controller
{
/**
* @param string $name
*/
public function index($name='name')
{
//获取学生A的所有数据
$student = Student::getByName('学生A'); //获取学生A是信息
$course=Course::getByName('语文'); //获取语文信息
$res= $student->Course()->attach($course); //给中间表插入数据
if($res){
echo '新增成功';
}
}
}
?>
好了,接下来我们刷新一下看看浏览器是不是显示新增成功了。
我们看到上图说明已经新增成功了。
然后‘学生A’的课程多了一些可能忙不过来,需要取消掉一些课程也是可以的。
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\Student;
use app\index\model\Course;
class index extends Controller
{
/**
* @param string $name
*/
public function index($name='name')
{
//获取学生A的所有数据
$student = Student::getByName('学生A');
$course=Course::getByName('地理');
$res= $student->Course()->detach($course);
if($res){
echo '取消成功';
}
}
}
?>
下面看看刷新结果:
开始的时候我看到这个以为是失败了,但是看看数据库’学生A’中间里的地理课程确实已经没有了。以为是哪里出错了就重新检查了一遍随便修改了’学生A’的课程在试一次发现浏览器上显示的还是一样的结果,数据库那条记录也还是又一次被删除了。具体原因现在还不清楚,不想深究了因为现在太晚了。请多多包涵哈,明天还要上班呢!
下面是数据库的所有记录,那条’学生A’的地理课程记录已经不在了。
关联查询
只要大家掌握好了上面的基本操作接下来的关联查询都会非常简单,我会尽量截图把每一个细节都截下来让大家看到。
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\Student;
class index extends Controller
{
/**
* @param string $name
*/
public function index($name='name')
{
//获取学生A的所有数据
$student=Student::getByName('学生A');
//因为获取到的数据都是数组里包含对象所以需要循环出数组里的对象在把每一个对象转为数组在输出
for($i=0;$i<count($student->Course);$i++){
var_dump($student->Course[$i]->toArray());
}
}
}
?>
上面这个是关联查询,因为获取到的是数据集需要循环转数组在输出才看的更清楚些。
下面是查询结果:
虽然只有一条新增的数据是不一样的,但是查询结果却是正确的。这是我插入数据的时候没有注意到的小细节,插入的时候一个学生连续好几节课都在学一个课程。不过没关系,因为我们只是在做测试只要测试的结果是正确的就ok了。
为了证明搜索结果是正确的我把 pwn_Stu_cour 中间表的数据截图上来,也方便理解一些。
我这里就介绍了几个查找,添加,删除的方法,目的是为了介绍更详细的使用流程,但不会每一个都介绍过去。那样子太耗时间了,也没必要。因为手册上已经都讲的很清楚了。
网友评论