PHPThink 3.2 关联模型自动验证问题的解决方法

浏览:1797 发布日期:2015/02/17 分类:技术分享 关键字: 关联模型 自动验证 自动完成 表单令牌
刚学PHPThink没多少天,今天做实例的时候就发现,对关联模型写入时使用create操作时,它会自动将我们定义的关联数据删掉,以至于无法写入关联数据。
网上搜到了两个方案,都是大幅度地改动框架代码,我试过之后,在开启表单令牌验证的条件下都失败了。
我分析了一下失败的原因,都是在写入时丢失了$this->options['link']与关联数据,又或者是将 表单验证的字段 保留了下来。所以我想只要能对create方法进行改进,让它对于关联数组保留$this->options['link']与关联数据,同时剔除 表单验证字段 即可。
我改动的代码如下    /**
     * 创建数据对象 但不保存到数据库
     * @access public
     * @param mixed $data 创建数据
     * @param string $type 状态
     * @return mixed
     */
     public function create($data='',$type='') {
        $is_link = $this->options['link']; //对$this->options['link']字段进行备份,因为后面有一个 数据自动验证 函数会删除这个属性
        // 如果没有传值默认取POST数据
        if(empty($data)) {
            $data   =   I('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?:(!empty($data[$this->getPk()])?self::MODEL_UPDATE:self::MODEL_INSERT);

        // 检查字段映射
        if(!empty($this->_map)) {
            foreach ($this->_map as $key=>$val){
                if(isset($data[$key])) {
                    $data[$val] =   $data[$key];
                    unset($data[$key]);
                }
            }
        }

        // 检测提交字段的合法性
        if(isset($this->options['field'])) { // $this->field('field1,field2...')->create()
            $fields =   $this->options['field'];
            unset($this->options['field']);
        }elseif($type == self::MODEL_INSERT && isset($this->insertFields)) {
            $fields =   $this->insertFields;
        }elseif($type == self::MODEL_UPDATE && isset($this->updateFields)) {
            $fields =   $this->updateFields;
        }
        if(isset($fields)) {
            if(is_string($fields)) {
                $fields =   explode(',',$fields);
            }
            // 判断令牌验证字段
            if(C('TOKEN_ON'))   $fields[] = C('TOKEN_NAME', null, '__hash__');
            foreach ($data as $key=>$val){
                if(!in_array($key,$fields)) {
                    unset($data[$key]);
                }
            }
        }

        // 数据自动验证
        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(!in_array($key,$fields)) {
                    if($is_link) { //如果是关联模型,则保留关联数据
                        if(!is_array($data[$key])) unset($data[$key]);
                    } else { //否则剔除非法字段
                        unset($data[$key]);
                    }
                }elseif(MAGIC_QUOTES_GPC && is_string($val)){
                    $data[$key] =   stripslashes($val);
                }
            }
        }
        $this->options['link'] = $is_link; //还原关联模型的属性
        // 创建完成对数据进行自动处理
        $this->autoOperation($data,$type);
        // 赋值当前数据对象
        $this->data =   $data;
        // 返回创建的数据以供其他调用
        return $data;
     }
这样,对关联模型的写入就可以使用 create() 方法进行验证了,而且支持表单令牌功能。
同时我觉得 数据自动验证 使得关联模型的$this->options['link']参数丢失应该是框架的一个bug,辛苦的工程师们也许可以考虑一下修正这个问题。
最后祝大家新年快乐!

附件 Model.class.zip ( 13.11 KB 下载:34 次 )

最佳答案
评论( 相关
后面还有条评论,点击查看>>