mysql关联表中间表主表三张表的使用

想了想我还是觉得在写一篇关于多对多的文档吧,因为我看了官方的文档写的不够细,不好理解。我自己也花了时间去看人家的文档还有自己又做了一些测试才知道怎么用的现在把我做测试的所有过程分享给大家。

数据库表与数据
就从数据库表开始啦,因为这样可能会更利于大家去理解。大家都知道数据库多对多关系都是需要三张表来完成的,一张主表,一张关联表,还有一张中间表。比如我们这里主表是学生表关联课程表。因为一个学生可以学多们课程,一门课程可以有多个学生来上课所以需要有一个中间表把他们关联起来。现在我就把今天需要做测试的几张表都贴出来,也方便大家在有不明白的时候可以拿来做测试。

下面这张是学生表:

  /*学生表*/

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 中间表的数据截图上来,也方便理解一些。

我这里就介绍了几个查找,添加,删除的方法,目的是为了介绍更详细的使用流程,但不会每一个都介绍过去。那样子太耗时间了,也没必要。因为手册上已经都讲的很清楚了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341