+ -
当前位置:首页 → 问答吧 → 数据表关联操作教程一,一对一关联

数据表关联操作教程一,一对一关联

时间:2009-12-31

来源:互联网

在一对一关联中,spLinker提供了几乎全部的spModel拥有的功能,在理解了spModel的基础知识后,很轻易就可以使用spLinker带来的关联功能了。

首先看例子,我们先准备了两个数据表,分别是用户表及用户详细资料表,为了方便讲述,这里的数据表都是简化的。

user 用户表

user_id int 用户ID 自增/主键

user_name varchar(50) 用户名 唯一

user_detail 用户详细资料表

user_id int 用户ID 主键

intro varchar(255) 用户个人介绍

一个用户记录对应着一个详细资料,因而这两个表是一对一的。正如前文所述,由于详细资料在逻辑上并非经常和用户表同时出现,所以我们将本来是相关的记录拆分成两个表来对待。(下面我们称user为本表,user_detail为对应表)

第二步,我们分别建立了这两个表的spModel继承类,代码如下:

user.php

复制代码
  1. <?php
  2. class user extends spModel
  3. {
  4. &#160;&#160;&#160;&#160;public $pk = 'user_id';
  5. &#160;&#160;&#160;&#160;public $table = 'user';
  6. &#160;&#160;&#160;&#160;// 由spModel的变量$linker来设置表间关联
  7. &#160;&#160;&#160;&#160;var $linker = array(
  8. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;array(
  9. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'type' => 'hasone',&#160;&#160; // 关联类型,这里是一对一关联
  10. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'map' => 'detail',&#160;&#160;&#160;&#160;// 关联的标识
  11. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'mapkey' => 'user_id', // 本表与对应表关联的字段名
  12. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'fclass' => 'user_detail', // 对应表的类名
  13. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'fkey' => 'user_id',&#160;&#160;&#160;&#160;// 对应表中关联的字段名
  14. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'enabled' => true&#160;&#160;&#160;&#160; // 启用关联
  15. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  16. &#160;&#160;&#160;&#160;);
  17. }


user_detail.php

复制代码
  1. <?php
  2. class user_detail extends spModel
  3. {
  4. &#160;&#160;&#160;&#160;public $pk = 'user_id';
  5. &#160;&#160;&#160;&#160;public $table = 'user_detail';
  6. }


我们看到,作为主表的user类,它使用了$linker来设置关联信息(本章的最后将详细介绍$linker的每个设置的作用)。$linker 是非常必要的,因为无论是作为模型类的变量出现,或者是在程序过程中动态地载入到spLinker中,都需要按照正确的格式去设置。

下面我们来介绍一对一关联的create,update,delete,find,findAll操作:

CREATE

首先,一般而言如果我们调用了user类的create方法,将在user表中新增一条记录。不过现在我们希望通过使用了一对一的关联,同时地将记录新增到主表和对应表上:

复制代码
  1. $newrow = array(
  2. &#160;&#160;&#160;&#160;'user_name' => "灰太狼",
  3. &#160;&#160;&#160;&#160;'detail' => array(&#160;&#160;// 请注意这里对应的就是$linker的'map' => 'detail',也就是关联的标识
  4. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'intro' => "草原上的王者" // 这里是增加到对应表上的数据
  5. &#160;&#160;&#160;&#160;),
  6. );
  7. $userObj = spClass("user");
  8. $userObj->spLinker()->create($newrow); // 和普通的create不同!


好了,看看两个数据表,数据已经如我们想象一样出现了:

user表

1 灰太狼

user_detail表

1 草原上的王者

在使用spLinker过程中,需要注意的地方如上面注释的,一个是关联的标识的作用,另一个是spLinker()->形式的函数调用。

引用
$userObj->spLinker()->create($newrow)这种形式的调用在sp框架内尤其是spModel的附属类内经常可以见到,这是一种提高代码写作效率和减少理解误差的好方法。它在spModel的意义就是附加的功能,比如$userObj->spPager()->findAll()就是在findAll上面附加了spPager分页的功能,本例中$userObj->spLinker()->create($newrow); 就是在create的时候加入了spLinker关联功能等等。建议大家能好好的熟悉这种写法,这将为我们的系统开发效率带来非常明显的改善。


UPDATE

在一对一的关联中,更新可以是对主表的记录更新,也可以是对对应表的记录进行更新。当然,前提是更新条件要在主表中都能有记录匹配。

复制代码
  1. $conditions = array('user_name' => "灰太狼"); // 和普通的update一样,首先是要有更新的条件,条件主要是针对主表的
  2. $updaterow = array( // 这里是需要更新的数据
  3. &#160;&#160;&#160;&#160;'detail' => array( // 注意detail指代的是什么
  4. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'intro' => "不像草原上的王者"
  5. &#160;&#160;&#160;&#160;),
  6. );
  7. $userObj = spClass("user");
  8. $userObj->spLinker()->update($conditions, $updaterow); // 完成更新


执行了上面代码后,我们再来看看两表:

user表

1 灰太狼

user_detail表

1 不像草原上的王者

显然这里只更新了对应表。当然,如果加入其他的更新数据,那么主表也是能够更新的。

DELETE

一对一的关联中,删除操作是会将两表的对应记录同时删除。

复制代码
  1. $conditions = array('user_name' => "灰太狼"); // 还是要设置对主表的条件
  2. $userObj = spClass("user");
  3. $userObj->spLinker()->delete($conditions); // 完成删除


FIND / FINDALL

我们并没有把find和findAll放到前面去讲述,这是因为我们希望能够先了解数据从何而来,再去熟悉数据的使用。

在spLinker的作用下,拥有表间关联的find和findAll,查找获取的结果都将带上关联表中的内容。

首先我们准备下面的表数据:

user表

1 灰太狼

2 小羊羊

user_detail表

1 不像草原上的王者

2 是一只羊

然后我们用find查找

复制代码
  1. $conditions = array("user_name"=>"小羊羊");
  2. $userObj = spClass("user");
  3. $result = $userObj->spLinker()->find($conditions);
  4. dump($result);


结果是:

复制代码
  1. Array
  2. (
  3. &#160;&#160;&#160;&#160;[user_id] => 2
  4. &#160;&#160;&#160;&#160;[user_name] => 小羊羊
  5. &#160;&#160;&#160;&#160;[detail] => Array
  6. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;(
  7. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_id] => 2
  8. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[intro] => 是一只羊
  9. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  10. )


我们看到detail的标识已经带上了对应表user_detail的记录了。

使用findAll查找

复制代码
  1. $userObj = spClass("user");
  2. $result = $userObj->spLinker()->findAll();
  3. dump($result);



结果是:

复制代码
  1. Array
  2. (
  3. &#160;&#160;&#160;&#160;[0] => Array
  4. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;(
  5. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_id] => 12
  6. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_name] => 灰太狼
  7. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[detail] => Array
  8. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;(
  9. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_id] => 12
  10. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[intro] => 不像草原上的王者
  11. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  12. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  13. &#160;&#160;&#160;&#160;[1] => Array
  14. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;(
  15. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_id] => 14
  16. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_name] => 小羊羊
  17. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[detail] => Array
  18. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;(
  19. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[user_id] => 14
  20. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;[intro] => 是一只羊
  21. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  22. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  23. )


主表和对应表的记录都能查找出来了。

以上,我们已经了解了spLinker的使用以及一对一关联的实例,接下来的教程中我们还将介绍一对多关联和多对多关联的用法。

在这里,我们还需要介绍一下$linker的全部属性,部分是上面已经介绍过的。

一、对本表内容而言

type,关联类型,只能取值"hasone","hasmany"和"manytomany"三者之一。

enabled,取值TRUE/FALSE,指示是否开启本关联

map,关联标识,在返回的结果里面标识关联内容的键值。

mapkey,本表中与对应表关联的字段名

二、对对应表内容而言

fclass,对应表的spModel继承类名称

fkey,对应表中与本表关联的字段名

三、在多对多情况中,还有

midclass,中间表的spModel继承类名称

四、对关联结果的限制

condition,对关联的附加条件,格式和findAll一样

countonly,取值TRUE/FALSE,在关联查找时是否只返回关联结果的记录数量,而并不返回全部结果。

sort',返回关联结果的排序,格式和findAll一样

field,返回关联结果的限定字段,格式和findAll一样

limit,返回关联结果的数量,格式和findAll一样

完整的 $linker 应该是:

复制代码
  1. &#160;&#160;&#160;&#160;var $linker = array(
  2. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;array(
  3. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'type' => 'hasmany',
  4. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'map' => 'ulink',
  5. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'mapkey' => 'user_id',
  6. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'fclass' => 'gb',
  7. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'fkey' => 'user_id',
  8. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'midclass' => 'user2gb',
  9. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'sort' => '', 'condition' => '', 'field' => '', 'limit' => '',
  10. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;'enabled' => true, 'countonly' => false
  11. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;),
  12. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;array(
  13. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;...
  14. &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;)
  15. );



本文地址:http://speedphp.com/post/splinker-hasone.html
[ 此帖被jake在2009-12-31 10:50重新编辑 ]

作者: jake   发布时间: 2009-12-31