Yii2 save操作详解

1、Yii2里面几种数据保存操作

1、通过显性的给数据模型的每一个属性赋值来执行数据的插入与更新

class Fans extends ActiveRecord
{
    public function demo(){
        $this->name = $name;
        $this->gender = $gender;
        $this->save();
    }
}

2、通过setAttributes方法

方式1

class Fans extends ActiveRecord
{
    public function demo(){
        $insert = [
            'name'=>$name,
            'gender'=>$gender
        ];
        $this->setAttributes($insert);
        $this->save();
    }
    public function rules()
    {
        return [
            [
                ['name','gender'],
                'safe'
            ]
        ];
    }
}

方式2

class Fans extends ActiveRecord
{
    public function demo(){
        $insert = [
            'name'=>$name,
            'gender'=>$gender
        ];
        $this->setAttributes($insert,false);
        $this->save();
    }
}

需要注意的是,我们在使用这种方式插入数据的时候,在第一种方式下,一定记得加上false。在第二种方式下,一定要记得记得将字段值加入rules中。下面贴出setAttributes和rules的源码:

public function setAttributes($values, $safeOnly = true)
    {
        if (is_array($values)) {
            $attributes = array_flip($safeOnly ? $this->safeAttributes() : $this->attributes());
            foreach ($values as $name => $value) {
                if (isset($attributes[$name])) {
                    $this->$name = $value;
                } elseif ($safeOnly) {
                    $this->onUnsafeAttribute($name, $value);
                }
            }
        }
    }

我们通过阅读setAttributes源码可知,第二个参数是来控制方法是否运行在safeonly模式之下,如果是的话,则不会为此AR模型去动态的设置属性,即不会主动的去构造$this->$name。这样会抛出'unsafe attribute'的异常。当然这些都是在执行rules判断之后发生的操作。

 public function createValidators()
    {
        $validators = new ArrayObject;
        foreach ($this->rules() as $rule) {
            if ($rule instanceof Validator) {
                $validators->append($rule);
            } elseif (is_array($rule) && isset($rule[0], $rule[1])) { // attributes, validator type
                $validator = Validator::createValidator($rule[1], $this, (array) $rule[0], array_slice($rule, 2));
                $validators->append($validator);
            } else {
                throw new InvalidConfigException('Invalid validation rule: a rule must specify both attribute names and validator type.');
            }
        }
        return $validators;
    }

我们通过分析上断源代码,会发现createValidators方法实际上是为我们将设置在rules方法里面的参数给append到类中。属性的设置是在createValidator方法中进行的。

3、通过执行原生的sql语句

class Fans extends ActiveRecord
{
    public function demo(){
        $sql = 'insert into ...';
        \Yii::$app->db->createCommand($sql)->execute()
    }

2、save的两种执行方式insert与update

通过看到save的源码我们可以看出,save可以执行insert和update两种操作,区别就在于$this->getIsNewRecord()的值。

    public function save($runValidation = true, $attributeNames = null)
    {
        if ($this->getIsNewRecord()) {
            return $this->insert($runValidation, $attributeNames);
        } else {
            return $this->update($runValidation, $attributeNames) !== false;
        }
    }

这是getIsNewRecord函数的注释"whether the record is new and should be inserted when calling [[save()]]",由此得知save方法的insert和update是通过AR记录是否是一条新纪录来判断的,而A是否是newRecord则是受AR对象是否是新对象来判断的,下面是官方文档给出的解释。

若 AR 对象是由 new 操作符 初始化出来的,save() 方法会在表里插入一条数据; 如果一个 AR 是由 find() 方法获取来的, 则 save() 会更新表里的对应行记录。
而且除了New,通过依赖注册的对象也是一个新对象。

添加新评论