2019-07-15 16:17:23 1757次浏览 3条回答 0 悬赏 10 金钱

Yii 2.0 ActiveRecord 插入数据库都时候,form 中的字段和数据表中的字段名不一致,怎么不改变 form 中都名称和数据表中的字段名,让他们完成一一映射,完成数据库插入,是用 ActiveRecord 中的 attributes() 吗还是,麻烦大佬给讲下,谢谢

类似于下面:
ThinkPHP 的字段映射功能可以让你在表单中隐藏真正的数据表字段,而不用担心放弃自动创建表单对象的功能,假设我们的 User 表里面有 username 和 email 字段,我们需要映射成另外的字段,定义方式如下:

Class UserModel extends Model{
    protected $_map = array(
        'name' =>'username', // 把表单中name映射到数据表的username字段
        'mail'  =>'email', // 把表单中的mail映射到数据表的email字段
    );
}

这样,在表单里面就可以直接使用 name 和 mail 名称作为表单数据提交了。在保存的时候会字段转换成定义的实际数据表字段。字段映射还可以支持对主键的映射。

最佳答案

  • Zhucola 发布于 2019-07-16 13:56 举报

    yii的attributeLabels和attributeHints是这样的

    public function getAttributeLabel($attribute)
    {
        $labels = $this->attributeLabels();
        return isset($labels[$attribute]) ? $labels[$attribute] : $this->generateAttributeLabel($attribute);
    }
    public function getAttributeHint($attribute)
    {
        $hints = $this->attributeHints();
        return isset($hints[$attribute]) ? $hints[$attribute] : '';
    }
    

    但是你的需求是要逆过来
    如果活动记录里面有name字段,你表单传过来的时候username

    //控制器里面
    public function actionModelTest(){
        $model = new TestModel(); //实例活动记录
        $model->username = "test";
    }
    //活动记录里面
    class TestMode extends ActiveRecord{
        
    }
    

    这样的活走的是模式方法get

    public function __get($name)
    {
        if (isset($this->_attributes[$name]) || array_key_exists($name, $this->_attributes)) {
            return $this->_attributes[$name];
        }
        if ($this->hasAttribute($name)) {
            return null;
        }
        if (isset($this->_related[$name]) || array_key_exists($name, $this->_related)) {
            return $this->_related[$name];
        }
        $value = parent::__get($name);
        if ($value instanceof ActiveQueryInterface) {
            $this->setRelationDependencies($name, $value);
            return $this->_related[$name] = $value->findFor($name, $this);
        }
    
        return $value;
    }
    

    核心就是hasAttribute方法,会去推到出表结构,然后判断是否存在,
    所以可以重新get魔术方法

    public $attributeMap = [
        "username" => name,
    ];
    public function __set($name, $value){
        if(isset($this->attributeMap[$name])){
            $this->setAttribute($this->attributeMap[$name],$value);
        } else {
            parent::__set($name, $value);
        }
    }
    

    一些yii的源码解析,欢迎star~
    https://github.com/Zhucola/yii_core_debug

  • 回答于 2019-07-15 17:10 举报

    Yii 中并没有内置 这样的功能,它推荐的做法是 单独定义一个继承自 yii\base\Model 的表单模型(区别于继承自 yii\db\ActiveRecord 的 AR 模型)。
    当然,自己仿照 TP 写这么一个字段映射的功能 也是 很容易的

  • 回答于 2019-07-18 17:28 举报

    我觉得按分层架构思想来处理,不应该是有数据模型层来处理转换,应该是创建一个filter(继承yii的filter)行为对数据进行转化,并且通过策略选择映射模式,这样,封装一个filter,就可以在所有模型和控制器提交之前做处理,只需要根据提交的不同表进行策略映射就行了。底层模型不要改动,ar模型只接受表映射的字段。如果上层提交过来的结构不满足,问题是出在上层,不应该要模型做改动。

    1 条回复
    回复于 2019-07-19 15:00 回复

    感谢大佬的讲解

    觉得很赞
您需要登录后才可以回答。登录 | 立即注册
零零零
主管

零零零

注册时间:2018-07-26
最后登录:2021-07-19
在线时长:17小时8分
  • 粉丝1
  • 金钱455
  • 威望0
  • 积分625

热门问题