Thinkphp3.2.3 解决关联模型的自动生成问题($_auto)

来源:互联网 发布:辐射4阴影优化补丁 编辑:程序博客网 时间:2024/06/05 20:57

在Thinkphp中,关联模型经常会被使用到,然而最近在使用的时候发现关联模型中的自动生成功能有些问题。
例如有一个类IdeaDetailModel对应表oidea_idea_detail,它有一个简表oidea_idea_simple(类IdeaSimpleModel),IdeaDetailModel代码如下(只保留了部分功能):

<?phpnamespace Idea\Model;use Think\Model\RelationModel;class IdeaDetailModel extends RelationModel{    protected $tableName = 'idea_detail';    /* 关系模型 */    protected $_link = array(        // 与IdeaSimple关联(一对一:HAS_ONE)        'Simple' => array(            'mapping_type' => self::HAS_ONE,            'class_name' => 'IdeaSimple',            'mapping_name' => 'Simple',            'foreign_key' => 'iid',            'relation_foreign_key' => 'id',            'mapping_fields' => 'star,heart,watch',        ),    );    /* Idea模型自动完成 */    protected $_auto = array(        array('read', 0, self::MODEL_INSERT),        array('comment', 0, self::MODEL_INSERT),        array('status', 1, self::MODEL_INSERT),        array('create_time', NOW_TIME, self::MODEL_INSERT),        array('update_time', NOW_TIME, self::MODEL_BOTH),    );    public function addIdea($uid, $arrIdeaInfo = null)    {        /*做些验证*/        //写入数据库        $data = array('src_uid' => $uid, 'title' => $arrIdeaInfo['title'], 'summary' => $arrIdeaInfo['summary']);        $data['Simple'] = $data;        $data['content'] = $arrIdeaInfo['content'];        $data = $this->create($data);        if (!$data) {            return false;        }        $res = $this->relation(array('Simple'))->add($data);        return $res;    } } 

IdeaSimpleModel类代码如下(只保留部分功能):

<?phpnamespace Idea\Model;use Think\Model\RelationModel;/****/class IdeaSimpleModel extends RelationModel{    /* Idea模型自动完成 */    protected $_auto = array(        array('star', 0, self::MODEL_INSERT),        array('heart', 0, self::MODEL_INSERT),        array('watch', 0, self::MODEL_INSERT),        array('status', 1, self::MODEL_INSERT),        array('update_time', NOW_TIME, self::MODEL_BOTH),    );}

如果我们调用IdeaDetailModel类的addIdea方法,实际上是不能实现IdeaSimpleModel中的自动完成功能的。

解决方法如下(参考了http://www.thinkphp.cn/code/833.html,实际上是对Think\RelationModel类的部分函数进行了覆盖,而我在其中添加了函数createRelationData):

<?phpnamespace Common\Model;use Think\Model\RelationModel;/** * 关联模型自动完成类,重载RelationModel中的create方法 * 在使用关联模型并且需要自动完成的时候使用该类 */class AutoCompleteRelationModel extends RelationModel{    /**     * 重载create方法,不过滤字段,并且生成需要数据     */    function create($data = '', $type = '') {        // 如果没有传值默认取POST数据        if (empty($data)) {            $data = $_POST;        } elseif (is_object($data)) {            $data = get_object_vars($data);        }        // 验证数据        if (empty($data) || !is_array($data)) {            $this->error = L('_DATA_TYPE_INVALID_');            return false;        }        // 状态        $type = $type ? $type : (!empty($data[$this->getPk() ]) ? self::MODEL_UPDATE : self::MODEL_INSERT);        // 数据自动验证        if (!$this->autoValidation($data, $type)) return false;        // 表单令牌验证        if (!$this->autoCheckToken($data)) {            $this->error = L('_TOKEN_ERROR_');            return false;        }        // 验证完成生成数据对象        if ($this->autoCheckFields) { // 开启字段检测 则过滤非法字段数据            $fields = $this->getDbFields();            foreach ($data as $key => $val) {                if (MAGIC_QUOTES_GPC && is_string($val)) {                    $data[$key] = stripslashes($val);                }            }        }        // 创建完成对数据进行自动处理        $data=$this->autoOperation($data, $type);        $data = $this->createRelationData($data);        // $data=$this->createData($data);        // 返回创建的数据以供其他调用        return $data;    }    /**     * 自动表单处理     * @access public     * @param array $data 创建数据     * @param string $type 创建类型     * @return mixed     */    private function autoOperation($data, $type) {        if (!empty($this->options['auto'])) {            $_auto = $this->options['auto'];            unset($this->options['auto']);        } elseif (!empty($this->_auto)) {            $_auto = $this->_auto;        }        // 自动填充        if (isset($_auto)) {            foreach ($_auto as $auto) {                // 填充因子定义格式                // array('field','填充内容','填充条件','附加规则',[额外参数])                if (empty($auto[2])) $auto[2] = self::MODEL_INSERT; // 默认为新增的时候自动填充                if ($type == $auto[2] || $auto[2] == self::MODEL_BOTH) {                    switch (trim($auto[3])) {                        case 'function': //  使用函数进行填充 字段的值作为参数                        case 'callback': // 使用回调方法                            $args = isset($auto[4]) ? (array)$auto[4] : array();                            if (isset($data[$auto[0]])) {                                array_unshift($args, $data[$auto[0]]);                            }                            if ('function' == $auto[3]) {                                $data[$auto[0]] = call_user_func_array($auto[1], $args);                            } else {                                $data[$auto[0]] = call_user_func_array(array(&$this,                                    $auto[1]                                ) , $args);                            }                            break;                        case 'field': // 用其它字段的值进行填充                            $data[$auto[0]] = $data[$auto[1]];                            break;                        case 'ignore': // 为空忽略                            if ('' === $data[$auto[0]]) unset($data[$auto[0]]);                            break;                        case 'string':                        default: // 默认作为字符串填充                            $data[$auto[0]] = $auto[1];                        }                        if (false === $data[$auto[0]]) unset($data[$auto[0]]);                    }            }        }        return $data;    }    /**     * 生成关联模型需要的数据     */    function createData($data) {        foreach ($data as $k => $v) {            if (in_array($k, $this->fields)) {                $data['Detail'][$k] = $v;                unset($data[$k]);            }        }        //删除多余字段        unset($data['nid']);        unset($data['create_date']);        return $data;    }    /**     * ADD     * 对关联模型使用D函数,从而实现自动完成     */    function createRelationData($data)    {        $linkKeys = array_keys($this->_link);        if (empty($linkKeys) || !is_array($linkKeys)) {            return $data;        }        $arrMappingName = array();        foreach ($linkKeys as $index => $key) {            if (isset($this->_link[$key]['mapping_name'])) {                array_push($arrMappingName, $this->_link[$key]['mapping_name']);                unset($linkKeys[$index]);            }        }        $arrMappingName = array_merge($arrMappingName, $linkKeys);        foreach ($data as $model => $item) {            if (in_array($model, $arrMappingName)) {                    $tempData = D($this->_link[$model]['class_name'])->create($item);                    $data[$model] = $tempData;            }        }        return $data;    }}

这样就可以让关联模型支持自动完成功能了。使用方法:

<?phpnamespace Idea\Model;use Common\Model\AutoCompleteRelationModel;// use Think\Model\RelationModel;/*** Idea model* 对应表oidea_idea*/class IdeaDetailModel extends AutoCompleteRelationModel{    /*同上,不变*/}

水平有限,欢迎指正~

0 0