关于关联模型
ThinkPHP 3.2.3 的关联模型(手册地址)一般处理关联数据表的 CURD 操作,例如关联读取、关联写入、关联删除等。
实例
博客管理模块关于博客有 4 张数据表:博客表 crm_blog:

CREATE TABLE `crm_blog` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(30) NOT NULL DEFAULT '',
  `content` text NOT NULL,
  `time` int(10) unsigned NOT NULL DEFAULT '0',
  `click` smallint(6) unsigned NOT NULL DEFAULT '0',
  `cid` int(10) unsigned NOT NULL,
  `del` tinyint(1) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `cid` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

属性表 crm_attr:

CREATE TABLE `crm_attr` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` char(10) NOT NULL DEFAULT '',
  `color` char(10) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

博客-属性关联表 crm_blog_attr:

CREATE TABLE `crm_blog_attr` (
  `bid` int(10) unsigned NOT NULL,
  `aid` int(10) unsigned NOT NULL,
  KEY `bid` (`bid`),
  KEY `aid` (`aid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

博客和属性是多对多的关系(MANY_TO_MANY)
类别表 crm_cate:

CREATE TABLE `crm_cate` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` char(20) NOT NULL DEFAULT '',
  `pid` int(10) unsigned NOT NULL DEFAULT '0',
  `sort` smallint(6) NOT NULL DEFAULT '100',
  PRIMARY KEY (`id`),
  KEY `pid` (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8

博客相对于类别是一对多(BELONGS_TO)关系,另一个角度类别相对于博客是多对一(HAS_MANY)关系
在 Admin 应用下创建 Model 类:./Application/Admin/Model/BlogRelationModel.class.php:

<?php
namespace Admin\Model;
use Think\Model\RelationModel;

class BlogRelationModel extends RelationModel {
    //如果Model文件名是BlogModel.class.php 就不需要定义$tableName
    protected $tableName = 'blog';//以blog表为基准表
    protected $_link = array(
        'attr'=>array(
            'mapping_name'=>'attr',
            'mapping_type'=>self::MANY_TO_MANY,//多对多关系
            'foreign_key'=>'bid',//中间表中blog的id
            'relation_foreign_key'=>'aid',//中间表中attr的id
            'relation_table'=>'crm_blog_attr'
        ),//定义关联表
        'cate'=>array( //博文和属性 一对多关系
            'mapping_name'=>'cate',
            'mapping_type'=>self::BELONGS_TO,//多(cate)关联一(blog)用 HAS_MANY,一(blog)关联多(cate)用BELONGS_TO
            'foreign_key'=>id, //blog表中的博文id
            'mapping_fields'=>'name', //只读取name字段
            'as_fields'=>'name:cate' //把cate表的name字段取出作为主表blod的字段展示并且把name改成cate(避免字段重复)
        )
    );
    
    //获取博文列表(包括没有删除的博文和回收站的博文,通过参数$type区分)
    public function get_blogs($type = 0) { //默认是没有删除的博文
        $field = array('cid','del');
        $where = array('del'=>$type);
        return $this->field($field,true)->relation(array('cate','attr'))->where($where)->select();
    }
}

说明:
Line 7:如果 Model 类的文件名是 BlogModel.class.php ,则不需要定义 protected $tableName = 'blog',否则要加上定义,因为实例化 Model 类时找不到 blogrelation 表,只有 blog 表
实例化 Model 类
控制器 ./Application/Admin/Controller/BlogController.class.php :

<?php
namespace Admin\Controller;
use Admin\Common\Category;

class BlogController extends CommonController{
    //博文列表
    public function index() {
        $this->blog = D('BlogRelation')->get_blogs();
        $this->display();
    }
    
    //添加博文
    public function add_blog() {
        //博文分类
        $cate = M('cate')->order('sort')->select();
        $this->cate = Category::level($cate);//一维数组无限极分类

        //博文属性
        $this->attr = M('attr')->select();
        
        $this->display();
    }
    
    //添加博文表单处理
   public function add_blog_handle() {
     
        $data = array(
            'title'=>I('title'),
            'content'=>I('content'),
            'time'=>time(),
            'click'=>I('click', 0, 'int'),
            'cid'=>I('cid'),
        );
        
        //属性插入到博文-属性中间表 开始
        /*if(isset($_POST['aid'])) {
            foreach($_POST['aid'] as $v) {
                $data['attr'][] = $v;//attr:关联表名称
            }
        }*/
        
        /*D('BlogRelation')->relation(true)->add($data);*/
        //$this->display('blog');//用于查看trace信息(config.php定义)
        //属性插入到博文-属性中间表 结束
        
        //自定义插入关联表(不使用关联模型)开始,哪种方法都可以
        if($bid = M('blog')->add($data)) {
            if(isset($_POST['aid'])) {
                $sql = 'INSERT INTO `'.C('DB_PREFIX').'blog_attr` (bid,aid) VALUES ';
                foreach($_POST['aid'] as $v) {
                    $sql .= '('.$bid.','.$v.'),';
                }
                $sql = rtrim($sql,',');
                M()->execute($sql);
            }
            $this->success('添加成功', U('Admin/Blog/index'));
        } else {
            $this->error('添加失败');
        }
        //自定义插入关联表(不使用关联模型)结束
        
    }
    
    
    //删除到回收站/还原
    public function to_recycle_bin () {
        $id = (int)$_GET['id'];
        $type = (int)$_GET['type'];
        $update = array(
            'id'=>$id,
            'del'=>$type
        );
        $msg = $type ? '删除' : '还原';
        $location = $type ? U('Admin/Blog/index','','') : U('Admin/Blog/recycle_bin','','');
        if(M('blog')->save($update)) {
            $this->success($msg.'成功' ,$location);
        } else {
            $this->error($msg.'失败');
        }
    }
    
    //回收站
    public function recycle_bin() {
        $this->blog = D('BlogRelation')->get_blogs(1);
        $this->display('index');
    }  
    
    //彻底删除
    public function delete() {
        $id = (int)$_GET['id'];
        //使用关联模型删除 或 手动删除
        if(D('BlogRelation')->relation('attr')->delete($id)) {
            $this->success('删除成功',U('Admin/Blog/recycle_bin'));
        } else {
            $this->error('删除失败');
        }        
    }
    
    //清空回收站
}

标签: none

添加新评论