thinkphp3.2 关联模型 具体实现

果然还是我太弱了,看了好多教程都没明白zen’怎么回事,每次轮到自己操作的时候就会sh失败。

记录下来,成功了方便以后自己使用。

问题1:数据库需要做xia相应的关系绑定吗?比如设置外键主键什么的?

外键不用设置,但是主键要设置。

附上官方3.1的relation示例(虽然是示例但是我用的是3.2感觉不会搭建3.1的,最后3.2的搭建成功了。)

-- 数据库: `examples`
-- --------------------------------------------------------
-- 表的结构 `think_card`

CREATE TABLE IF NOT EXISTS `think_card` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `member_id` mediumint(6) NOT NULL,
  `card` varchar(25) CHARACTER SET latin1 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=20 ;

-- --------------------------------------------------------
-- 表的结构 `think_dept`

CREATE TABLE IF NOT EXISTS `think_dept` (
  `id` smallint(3) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

-- 转存表中的数据 `think_dept`

INSERT INTO `think_dept` (`id`, `name`) VALUES
(1, '开发部'),
(2, '销售部'),
(3, '财务部');

-- --------------------------------------------------------
-- 表的结构 `think_groups`

CREATE TABLE IF NOT EXISTS `think_groups` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

-- 转存表中的数据 `think_groups`

INSERT INTO `think_groups` (`id`, `name`) VALUES
(1, '项目组1'),
(2, '项目组2'),
(3, '项目组3');

-- --------------------------------------------------------
-- 表的结构 `think_member`

CREATE TABLE IF NOT EXISTS `think_member` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) NOT NULL,
  `dept_id` smallint(3) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

-- --------------------------------------------------------
-- 表的结构 `think_member_groups`

CREATE TABLE IF NOT EXISTS `think_member_groups` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `groups_id` mediumint(5) NOT NULL,
  `member_id` mediumint(5) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=333 ;

-- --------------------------------------------------------
-- 表的结构 `think_profile`

CREATE TABLE IF NOT EXISTS `think_profile` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `member_id` mediumint(6) NOT NULL,
  `email` varchar(255) NOT NULL,
  `nickname` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

从sql中可以看出并没有做外键约束(就可以使用了),当然约束不约束的,我还是个弱鸡以后慢慢了解哪样好。

官方3.2的文档是写的很清楚了,但是还是不会做,是我太笨了吗?我在想是我做的和官方的示例有什么区别吗?

仔细看区别在哪里。

问题2:示例的模型是怎么绑定的?

这里我起初一直失败,看了对比才发现问题,于是我增加了self::下面代码中所有self::都是我加的

<?php

namespace Home\Model;//3.1示例原文没有这两句
use Think\Model\RelationModel;//当然3.2是这么做的
class MemberModel extends RelationModel {
    protected $_link =  array(  //关联保存的规则://这里我也做了对应的修改,3.1示例内没有self::
        'Profile'   =>  self::HAS_ONE,        //HAS_ONE 关联数据的更新直接赋值
        'Dept'      =>  self::BELONGS_TO,     //关联数据的更新直接赋
        'Card'      =>  self::HAS_MANY,       //HAS_MANY 的关联数据如果传入主键的值 则表示更新 否则就表示新增
        'Groups'    =>  self::MANY_TO_MANY,   //更新是删除之前的数据后重新写入
    );
}
问题3:看不懂示例这里,我查看其他例子有一些也都是这么写的为什么?

class IndexAction extends Action
我就直接写在自己的控制器的方法里。

public function hello(){
        $User = D("Member");
        $info[] =   '关联数据操作开始';
        G('1');
        // 添加用户数据
        $User->name     = 'thinkphp';
        $User->dept_id  = 1;
        // 用户档案数据
        $User->Profile  = array(
            'email'     => 'liu21st@gmail.com',
            'nickname'  => '流年',
        );
        // 用户的银行卡数据
        $User->Card     = array(
            array('id'=>1,'card' => '12345678'),
            array('id'=>2,'card' => '88888888'),
        );
        // 用户的所属项目组数据
        $User->Groups = array(
            array('id' => 1),
            array('id' => 2),
        );
        $info[] =   '<div class="result">'.dump($User->data(),false).'</div>';
        // 关联添加用户数据
        $id = $User->relation(true)->add();
        $info[] =   '用户数据关联写入完成!用时:'.G('1','2',6).'s';

        // 关联查询
        $user = $User->relation(true)->find($id);
        $info[] =   '查询用户ID为'.$id.'的所有关联数据,用时:'.G('2','3',6).'s';
        $info[] =   '<div class="result">'.dump($user,false).'</div>';
        $user = $User->relation('Profile')->find($id);
        $info[] =   '查询用户ID为'.$id.'的用户档案关联数据,用时:'.G('3','4',6).'s';
        $info[] =   '<div class="result">'.dump($user,false).'</div>';
        $list = $User->relation('Card')->order('id desc')->limit(2)->select();
        $info[] =   '查询用户的数据集并包含用户银行卡关联数据,用时:'.G('4','5',6).'s';
        foreach ($list as $key=>$val){
            $info[] =   '<div class="result">'.dump($val,false).'</div>';
        }
        G('6');
        // 关联更新
        $user['id']     = $id;
        $user['name']   = 'tp';
        // HAS_ONE 关联数据的更新直接赋值
        $user['Profile']['email'] = 'thinkphp@qq.com';
        $user['dept_id'] = 2;
        // 注意HAS_MANY 的关联数据要加上主键的值
        // 可以更新部分数据
        $user['Card']   = array(
            array('id'  => 1, 'card' => '66666666'), // 更新主键为1的记录
            array('card'=> '77777777'), // 增加一条新的记录
        );

        // MANY_TO_MANY 的数据更新是重新写入
        $user['Groups'] = array(
            array('id'  => 2),
            array('id'  => 3),
        );
        $User->where(array('id'=>$id))->relation(true)->save($user);
        $info[] =   '用户数据关联更新完成!用时:'.G('6','7',6).'s';
        // 查询更新后的数据
        $user = $User->relation(true)->find($id);
        $info[] =   '查询更新后的用户ID为'.$id.'的用户关联数据,用时:'.G('7','8',6).'s';
        $info[] =   '<div class="result">'.dump($user,false).'</div>';

        // 关联删除
        $User->relation(true)->delete($id);
        $info[] =   '用户ID为' . $id . '数据关联删除完成!用时:'.G('8','9',6).'s';
        $this->assign('info',$info);
        $this->display();
    }

然后我把示例里的tpl放在view里对应的hello.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> ThinkPHP示例:关联操作 </title>
<style type="text/css">
*{ padding: 0; margin: 0;font-size:16px; font-family: "微软雅黑"} 
div{ padding: 25px 20px;} 
body{ background: #fff; color: #333;}
h2{font-size:36px}
div.result{border:1px solid #d4d4d4;background:#FFC;color:#393939; padding:8px 20px;float:auto; width:450px;margin:2px}
pre{font-size:12px;}
</style>
</head>
<body>

<div >
	<h2>ThinkPHP示例:关联操作</h2>
	<foreach name="info" item="i">
	{$i}<br/>
	</foreach>
</div>
</body>
</html>

于是3.2的关联模型就运行成功了。

说起来很简单,但是做起来还是出问题,当然成功一次后应该就好了哈哈。

好了,现在要开始做修改了。

  1. 把think_member表内的idzi’d字段改成uid。

其他一切不变。进行关联添加操作。

我发现操作一切正常。

这里出现了一点小问题,是我对D函数的理解不透彻,我平时用的时候都直接写数据库的表名都可以正常访问使用。

实际上看文档的意思是D或者M对应的是实例化模型,模型首字母大写,所以正确的写法应该是D(‘Member’)捂脸,不知道我这些年都是怎么写的。

这个习惯导致了一个问题!

添加数据的时候示例使用的是对象的方式添加的

$User->Profile  = array(
            'email'     => 'liu21st@gmail.com',
            'nickname'  => '流年',
        );

而我是使用数组的方式添加的

$data = array();
        $data['name']='张三';
        $data['dept_id']=66;
        $data['Profile']=array(
            'email' => 'zhangsan@qq.com',
            'nickname'  => '流年',
        );

这里刚开始操作的时候失败了,我仔细检查了下原因,原来是Profile写成 了profile导致的,这里对应的竟然是大写的,小写不行。还有绑定关系的时候也要注意都是大写的,顾名思义,是关联“模型”模型首字母大写,我错误的用法导致了不区分大小写的操作。

'Card'      =>  self::HAS_MANY,

好了,到了这里,仅仅修改了一个member表的id改成uid,一切正常。记录下。

接下来,修改了profile表的字段,把member_id改成了uid,出问题了。

foreign_key : 关联的外键名称

外键的默认规则是当前数据对象名称_id,例如: UserModel对应的可能是表think_user (注意:think只是一个表前缀,可以随意配置) 那么think_user表的外键默认为 user_id,如果不是,就必须在定义关联的时候显式定义 foreign_key 。

果然还是我太弱了,看了好多教程都没明白zen’怎么回事,每次轮到自己操作的时候就会sh失败。

记录下来,成功了方便以后自己使用。

问题4:数据库需要做xia相应的关系绑定吗?比如设置外键主键什么的?

外键不用设置,但是主键要设置。

附上官方3.1的relation示例(虽然是示例但是我用的是3.2感觉不会搭建3.1的,最后3.2的搭建成功了。)

-- 数据库: `examples`
-- --------------------------------------------------------
-- 表的结构 `think_card`

CREATE TABLE IF NOT EXISTS `think_card` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `member_id` mediumint(6) NOT NULL,
  `card` varchar(25) CHARACTER SET latin1 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=20 ;

-- --------------------------------------------------------
-- 表的结构 `think_dept`

CREATE TABLE IF NOT EXISTS `think_dept` (
  `id` smallint(3) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

-- 转存表中的数据 `think_dept`

INSERT INTO `think_dept` (`id`, `name`) VALUES
(1, '开发部'),
(2, '销售部'),
(3, '财务部');

-- --------------------------------------------------------
-- 表的结构 `think_groups`

CREATE TABLE IF NOT EXISTS `think_groups` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=4 ;

-- 转存表中的数据 `think_groups`

INSERT INTO `think_groups` (`id`, `name`) VALUES
(1, '项目组1'),
(2, '项目组2'),
(3, '项目组3');

-- --------------------------------------------------------
-- 表的结构 `think_member`

CREATE TABLE IF NOT EXISTS `think_member` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `name` varchar(25) NOT NULL,
  `dept_id` smallint(3) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

-- --------------------------------------------------------
-- 表的结构 `think_member_groups`

CREATE TABLE IF NOT EXISTS `think_member_groups` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `groups_id` mediumint(5) NOT NULL,
  `member_id` mediumint(5) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=333 ;

-- --------------------------------------------------------
-- 表的结构 `think_profile`

CREATE TABLE IF NOT EXISTS `think_profile` (
  `id` mediumint(6) NOT NULL AUTO_INCREMENT,
  `member_id` mediumint(6) NOT NULL,
  `email` varchar(255) NOT NULL,
  `nickname` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=18 ;

从sql中可以看出并没有做外键约束(就可以使用了),当然约束不约束的,我还是个弱鸡以后慢慢了解哪样好。

官方3.2的文档是写的很清楚了,但是还是不会做,是我太笨了吗?我在想是我做的和官方的示例有什么区别吗?

仔细看区别在哪里。

问题5:示例的模型是怎么绑定的?

这里我起初一直失败,看了对比才发现问题,于是我增加了self::下面代码中所有self::都是我加的


<?php
namespace Home\Model;//3.1示例原文没有这两句
use Think\Model\RelationModel;//当然3.2是这么做的
class MemberModel extends RelationModel {
    protected $_link =  array(  //关联保存的规则://这里我也做了对应的修改,3.1示例内没有self::
        'Profile'   =>  self::HAS_ONE,        //HAS_ONE 关联数据的更新直接赋值
        'Dept'      =>  self::BELONGS_TO,     //关联数据的更新直接赋
        'Card'      =>  self::HAS_MANY,       //HAS_MANY 的关联数据如果传入主键的值 则表示更新 否则就表示新增
        'Groups'    =>  self::MANY_TO_MANY,   //更新是删除之前的数据后重新写入
    );
} 
问题6:看不懂示例这里,我查看其他例子有一些也都是这么写的为什么?
class IndexAction extends Action 

我就直接写在自己的控制器的方法里。

public function hello(){
        $User = D("Member");
        $info[] =   '关联数据操作开始';
        G('1');
        // 添加用户数据
        $User->name     = 'thinkphp';
        $User->dept_id  = 1;
        // 用户档案数据
        $User->Profile  = array(
            'email'     => 'liu21st@gmail.com',
            'nickname'  => '流年',
        );
        // 用户的银行卡数据
        $User->Card     = array(
            array('id'=>1,'card' => '12345678'),
            array('id'=>2,'card' => '88888888'),
        );
        // 用户的所属项目组数据
        $User->Groups = array(
            array('id' => 1),
            array('id' => 2),
        );
        $info[] =   '<div class="result">'.dump($User->data(),false).'</div>';
        // 关联添加用户数据
        $id = $User->relation(true)->add();
        $info[] =   '用户数据关联写入完成!用时:'.G('1','2',6).'s';

        // 关联查询
        $user = $User->relation(true)->find($id);
        $info[] =   '查询用户ID为'.$id.'的所有关联数据,用时:'.G('2','3',6).'s';
        $info[] =   '<div class="result">'.dump($user,false).'</div>';
        $user = $User->relation('Profile')->find($id);
        $info[] =   '查询用户ID为'.$id.'的用户档案关联数据,用时:'.G('3','4',6).'s';
        $info[] =   '<div class="result">'.dump($user,false).'</div>';
        $list = $User->relation('Card')->order('id desc')->limit(2)->select();
        $info[] =   '查询用户的数据集并包含用户银行卡关联数据,用时:'.G('4','5',6).'s';
        foreach ($list as $key=>$val){
            $info[] =   '<div class="result">'.dump($val,false).'</div>';
        }
        G('6');
        // 关联更新
        $user['id']     = $id;
        $user['name']   = 'tp';
        // HAS_ONE 关联数据的更新直接赋值
        $user['Profile']['email'] = 'thinkphp@qq.com';
        $user['dept_id'] = 2;
        // 注意HAS_MANY 的关联数据要加上主键的值
        // 可以更新部分数据
        $user['Card']   = array(
            array('id'  => 1, 'card' => '66666666'), // 更新主键为1的记录
            array('card'=> '77777777'), // 增加一条新的记录
        );

        // MANY_TO_MANY 的数据更新是重新写入
        $user['Groups'] = array(
            array('id'  => 2),
            array('id'  => 3),
        );
        $User->where(array('id'=>$id))->relation(true)->save($user);
        $info[] =   '用户数据关联更新完成!用时:'.G('6','7',6).'s';
        // 查询更新后的数据
        $user = $User->relation(true)->find($id);
        $info[] =   '查询更新后的用户ID为'.$id.'的用户关联数据,用时:'.G('7','8',6).'s';
        $info[] =   '<div class="result">'.dump($user,false).'</div>';

        // 关联删除
        $User->relation(true)->delete($id);
        $info[] =   '用户ID为' . $id . '数据关联删除完成!用时:'.G('8','9',6).'s';
        $this->assign('info',$info);
        $this->display();
    }

然后我把示例里的tpl放在view里对应的hello.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title> ThinkPHP示例:关联操作 </title>
<style type="text/css">
*{ padding: 0; margin: 0;font-size:16px; font-family: "微软雅黑"} 
div{ padding: 25px 20px;} 
body{ background: #fff; color: #333;}
h2{font-size:36px}
div.result{border:1px solid #d4d4d4;background:#FFC;color:#393939; padding:8px 20px;float:auto; width:450px;margin:2px}
pre{font-size:12px;}
</style>
</head>
<body>

<div >
	<h2>ThinkPHP示例:关联操作</h2>
	<foreach name="info" item="i">
	{$i}<br/>
	</foreach>
</div>
</body>
</html>

于是3.2的关联模型就运行成功了。

说起来很简单,但是做起来还是出问题,当然成功一次后应该就好了哈哈。

好了,现在要开始做修改了。

  1. 把think_member表内的字段改成uid。

其他一切不变。进行关联添加操作。

我发现操作一切正常。

这里出现了一点小问题,是我对D函数的理解不透彻,我平时用的时候都直接写数据库的表名都可以正常访问使用。

实际上看文档的意思是D或者M对应的是实例化模型,模型首字母大写,所以正确的写法应该是D(‘Member’)捂脸,不知道我这些年都是怎么写的。

这个习惯导致了一个问题!

添加数据的时候示例使用的是对象的方式添加的

$User->Profile  = array(
            'email'     => 'liu21st@gmail.com',
            'nickname'  => '流年',
        );
而我是使用数组的方式添加的

$data = array();
        $data['name']='张三';
        $data['dept_id']=66;
        $data['Profile']=array(
            'email' => 'zhangsan@qq.com',
            'nickname'  => '流年',
        );

这里刚开始操作的时候失败了,我仔细检查了下原因,原来是Profile写成 了profile导致的,这里对应的竟然是大写的,小写不行。还有绑定关系的时候也要注意都是大写的,顾名思义,是关联“模型”模型首字母大写,我错误的用法导致了不区分大小写的操作。

'Card'      =>  self::HAS_MANY,

好了,到了这里,仅仅修改了一个member表的id改成uid,一切正常。记录下。

接下来,修改了profile表的字段,把member_id改成了uid,出问题了。

foreign_key : 关联的外键名称

外键的默认规则是当前数据对象名称_id,例如: UserModel对应的可能是表think_user (注意:think只是一个表前缀,可以随意配置) 那么think_user表的外键默认为 user_id,如果不是,就必须在定义关联的时候显式定义 foreign_key 。

这里是官方3.2文档的描述(我打字太快,老是会出英文,这编辑器真cha’差劲,切换到mdshi’试试…额,谁教教我怎么转换?)

再次注意,foreign_key对应的是要绑定的模型(Profile)的对应的表内的字段名,而这个字段名就是外键,名字不要求和Member模型内的主键名字(最初是id,后来改成了uid)一致,但是要求这个uid是member表对应的主键,不然怎么叫外键呢。
绑定的时候Profile的uid和Member的主键(id,后来改成uid)绑定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值