浅谈FleaPHP中的表关联!
在关系数据库应用中,都离不开表与表的关联,表与表之间建立了关联关系后就可以提供很多方便的操作了,比如我要查询一个学生的信息,如果不建立学生与班 级的关系的话,那么,只可以显示出学生的基本信息,而学生是属于某一个班级的,我现在想知道这个学生的信息与该学生所在的班级的信息,甚至是该学生的任课 老师等信息,建立了学生表,与班级表,老师表之间的关系就方便好多了,用一个学生ID就可以查找出所有相关联的数据。
在FleaPHP中,支持以下四种关联关系:
分别对应FLEA_Db_TableDataGateway表中的 $hasOne,$hasMany,$manyToMany,$belongsTo 属性
我们下面就用 老师,学生,学生档案,班级的例子说说这几个关系。
以下是SQL代码:
//学生表
Create TABLE `testDB`.`student` (
`stu_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`stu_name` VARCHAR(20) NOT NULL,
`stu_class_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`stu_id`)
)
//学生档案表
Create TABLE `testDB`.`stu_record` (
`record_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`stu_id` INTEGER UNSIGNED NOT NULL,
`family_add` VARCHAR(150) NULL,
`family_tel` VARCHAR(20) NULL,
PRIMARY KEY (`record_id`)
)
//教师表
Create TABLE `testDB`.`teacher` (
`teacher_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`teacher_name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`teacher_id`)
)
//班级表
Create TABLE `testDB`.`classes` (
`class_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`class_name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`class_id`)
)
//由于教师与班级是多对多关系,所有建立一个中间连接表以表示该关联
Create TABLE `testDB`.`link_teacher_classes` (
`link_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`teacher_id` INTEGER UNSIGNED NOT NULL,
`class_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`link_id`)
)
现在,建好表之后,我们还要写几个继承自FLEA_Db_TableDataGateway父类的类,以对应数据库中的Student,Teacher,Classes表(连接表不用了)如下:
//学生表对应的类
class Model_Student extends FLEA_Db_TableDataGateway{
var $tableName = 'student';
var $primaryKey = 'stu_id';
/*
这是一对一关系,一个学生对应唯一的一个Record档案
tableClass 对应要与之关联一对一的表的对象类,即档案表的类
foreignKey是在档案表中,对应学生表的一个外键接连字段,
用该字段标识该档案属于哪个学生
mappingName 就是用于在你查询学生信息时,学生档案字段的别名
*/
var $hasOne = array(
'tableClass' => 'Model_Record',
'foreignKey' => 'stu_id',
'mappingName' => 'record'
);
/*
这是从属关系,一个学生属于某一个班级,换过来说就是班级与学生一对多,
一个班级有多个学生,而学生就只属于一个班级
tableClass 指定该类要与之有从属关系的类,这里是班级类
foreignKey 这里指定的是该表里的连接外表的字段,这里是学生表的班级ID字段
注意:这里的foreignKey指的是本表的字段,而上面hasOne关系中的foreignKey
指的是外表中的字段,要注意区分清楚
mappingName这里就不多说了,跟上面的一样,也是用于显示区分的别名
*/
var $belongsTo = array(
array(
'tableClass' => 'Model_Classes',
'foreignKey' => 'stu_class_id',
'mappingName' => 'class'
)
);
}
//档案表对应的类
class Model_Record extends FLEA_Db_TableDataGateway{
var $tableName = 'stu_record';
var $primaryKey = 'record_id';
}
//教师表对应的类
class Model_Teacher extends FLEA_Db_TableDataGateway{
var $tableName = 'teacher';
var $primaryKey = 'teacher_id';
/*
这里确立了教师与班级的多对多关系,一个教师可以教多个班级
而一个班级也有多个教师
tableClass 指定要建立多对多关系的表的类
joinTable 这个属性要注意一个,这个是指定教师表与班级表关系的连接表
由于二维表的数据结构的原因,所以多对多关系要用一个中间表(即连接表)来表示
连接表中就指明两个表各自的主键ID就可以了,以两个字段作复合主键,如不用复合
主键,就新增加一个字段作主键也可,这没关系
*/
var $manyToMany = array(
array(
'tableClass' => 'Model_Classes',
'mappingName' => 'class',
'joinTable' => 'link_teacher_classes',
)
);
}
class Model_Classes extends FLEA_Db_TableDataGateway{
var $tableName = 'classes';
var $primaryKey = 'class_id';
/*
这里确立了班级与学生的一对多关系
tableClass 指定该表的类要与哪个表的类建立一对多关系
foreignKey 外键ID,这里即指定学生表中定义的班级ID,这个是外表的字段
*/
var $hasMany = array(
array(
'tableClass' => 'Model_Student',
'foreignKey' => 'stu_class_id',
'mappingName' => 'students'
)
);
var $manyToMany = array(
// 由于多对多关系是双向的,所以班级表也可以定义上与教师表的多对多关系
// 也可以不写,看需求而定,比如你想查看某个班级信息时,一并显示该班
// 有多少个任课老师的话,那就在这个班级类里加上关系,我这里就不写了。。。
);
}
以上的代码就建立好了关系了,现在只管使用就是了。
不过还提醒大家一点,在每个关系里,都有一个 ‘enabled’ 的属性,如果设置为 false的话,则是将该关系禁掉,所以查询出来的结果就没有该关系的相应数据,这样可以节省效率,按需要时才打开相应的关联,该属性默认为true 可以如下设置:
array(
'tableClass' => 'Model_Student',
'foreignKey' => 'stu_class_id',
'mappingName' => 'students',
‘enabled’ => false
)
现在我们来测试一下数据。(事先自行插入几行数据用以测试)
$classManager = FLEA::getSingleton('Model_Classes');
$class =& $classManager->find(array('class_id' => 1));
dump($class);
出现结果如下:
这个例子已含盖了这四个关联关系的基本用法了,其它的就由你们来探索了,
在关系数据库应用中,都离不开表与表的关联,表与表之间建立了关联关系后就可以提供很多方便的操作了,比如我要查询一个学生的信息,如果不建立学生与班 级的关系的话,那么,只可以显示出学生的基本信息,而学生是属于某一个班级的,我现在想知道这个学生的信息与该学生所在的班级的信息,甚至是该学生的任课 老师等信息,建立了学生表,与班级表,老师表之间的关系就方便好多了,用一个学生ID就可以查找出所有相关联的数据。
在FleaPHP中,支持以下四种关联关系:
- HAS_ONE
- HAS_MANY
- MANY_TO_MANY
- BELONGS_TO
分别对应FLEA_Db_TableDataGateway表中的 $hasOne,$hasMany,$manyToMany,$belongsTo 属性
我们下面就用 老师,学生,学生档案,班级的例子说说这几个关系。
以下是SQL代码:
程序代码
//学生表
Create TABLE `testDB`.`student` (
`stu_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`stu_name` VARCHAR(20) NOT NULL,
`stu_class_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`stu_id`)
)
//学生档案表
Create TABLE `testDB`.`stu_record` (
`record_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`stu_id` INTEGER UNSIGNED NOT NULL,
`family_add` VARCHAR(150) NULL,
`family_tel` VARCHAR(20) NULL,
PRIMARY KEY (`record_id`)
)
//教师表
Create TABLE `testDB`.`teacher` (
`teacher_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`teacher_name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`teacher_id`)
)
//班级表
Create TABLE `testDB`.`classes` (
`class_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`class_name` VARCHAR(20) NOT NULL,
PRIMARY KEY (`class_id`)
)
//由于教师与班级是多对多关系,所有建立一个中间连接表以表示该关联
Create TABLE `testDB`.`link_teacher_classes` (
`link_id` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
`teacher_id` INTEGER UNSIGNED NOT NULL,
`class_id` INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (`link_id`)
)
现在,建好表之后,我们还要写几个继承自FLEA_Db_TableDataGateway父类的类,以对应数据库中的Student,Teacher,Classes表(连接表不用了)如下:
程序代码
//学生表对应的类
class Model_Student extends FLEA_Db_TableDataGateway{
var $tableName = 'student';
var $primaryKey = 'stu_id';
/*
这是一对一关系,一个学生对应唯一的一个Record档案
tableClass 对应要与之关联一对一的表的对象类,即档案表的类
foreignKey是在档案表中,对应学生表的一个外键接连字段,
用该字段标识该档案属于哪个学生
mappingName 就是用于在你查询学生信息时,学生档案字段的别名
*/
var $hasOne = array(
'tableClass' => 'Model_Record',
'foreignKey' => 'stu_id',
'mappingName' => 'record'
);
/*
这是从属关系,一个学生属于某一个班级,换过来说就是班级与学生一对多,
一个班级有多个学生,而学生就只属于一个班级
tableClass 指定该类要与之有从属关系的类,这里是班级类
foreignKey 这里指定的是该表里的连接外表的字段,这里是学生表的班级ID字段
注意:这里的foreignKey指的是本表的字段,而上面hasOne关系中的foreignKey
指的是外表中的字段,要注意区分清楚
mappingName这里就不多说了,跟上面的一样,也是用于显示区分的别名
*/
var $belongsTo = array(
array(
'tableClass' => 'Model_Classes',
'foreignKey' => 'stu_class_id',
'mappingName' => 'class'
)
);
}
//档案表对应的类
class Model_Record extends FLEA_Db_TableDataGateway{
var $tableName = 'stu_record';
var $primaryKey = 'record_id';
}
//教师表对应的类
class Model_Teacher extends FLEA_Db_TableDataGateway{
var $tableName = 'teacher';
var $primaryKey = 'teacher_id';
/*
这里确立了教师与班级的多对多关系,一个教师可以教多个班级
而一个班级也有多个教师
tableClass 指定要建立多对多关系的表的类
joinTable 这个属性要注意一个,这个是指定教师表与班级表关系的连接表
由于二维表的数据结构的原因,所以多对多关系要用一个中间表(即连接表)来表示
连接表中就指明两个表各自的主键ID就可以了,以两个字段作复合主键,如不用复合
主键,就新增加一个字段作主键也可,这没关系
*/
var $manyToMany = array(
array(
'tableClass' => 'Model_Classes',
'mappingName' => 'class',
'joinTable' => 'link_teacher_classes',
)
);
}
class Model_Classes extends FLEA_Db_TableDataGateway{
var $tableName = 'classes';
var $primaryKey = 'class_id';
/*
这里确立了班级与学生的一对多关系
tableClass 指定该表的类要与哪个表的类建立一对多关系
foreignKey 外键ID,这里即指定学生表中定义的班级ID,这个是外表的字段
*/
var $hasMany = array(
array(
'tableClass' => 'Model_Student',
'foreignKey' => 'stu_class_id',
'mappingName' => 'students'
)
);
var $manyToMany = array(
// 由于多对多关系是双向的,所以班级表也可以定义上与教师表的多对多关系
// 也可以不写,看需求而定,比如你想查看某个班级信息时,一并显示该班
// 有多少个任课老师的话,那就在这个班级类里加上关系,我这里就不写了。。。
);
}
以上的代码就建立好了关系了,现在只管使用就是了。
不过还提醒大家一点,在每个关系里,都有一个 ‘enabled’ 的属性,如果设置为 false的话,则是将该关系禁掉,所以查询出来的结果就没有该关系的相应数据,这样可以节省效率,按需要时才打开相应的关联,该属性默认为true 可以如下设置:
程序代码
array(
'tableClass' => 'Model_Student',
'foreignKey' => 'stu_class_id',
'mappingName' => 'students',
‘enabled’ => false
)
现在我们来测试一下数据。(事先自行插入几行数据用以测试)
程序代码
$classManager = FLEA::getSingleton('Model_Classes');
$class =& $classManager->find(array('class_id' => 1));
dump($class);
出现结果如下:
这个例子已含盖了这四个关联关系的基本用法了,其它的就由你们来探索了,