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

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

<?php
namespace 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类代码如下(只保留部分功能):

<?php

namespace 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):

<?php

namespace 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;
    }
}

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

<?php

namespace Idea\Model;

use Common\Model\AutoCompleteRelationModel;
// use Think\Model\RelationModel;

/**
* Idea model
* 对应表oidea_idea
*/
class IdeaDetailModel extends AutoCompleteRelationModel
{
    /*同上,不变*/
}

水平有限,欢迎指正~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值