yii2 关于 load 和 save 那些事儿

话不多说,直奔主题!

直接上源码分析:

    public function load($data, $formName = null)
    {
        // 调用load 一般我是 $test = new test()
        // $test->load('参数1','参数2')
        // 参数1 一般是post  get  传过来的参数 第二个参数 是一个空字符串 '';
        // $this->formName()  返回的额是 你实例化的类的名字  new test()  最后返回的是test
        $scope = $formName === null ? $this->formName() : $formName;
        if ($scope === '' && !empty($data)) {
            $this->setAttributes($data);  //进入

            return true;
        } elseif (isset($data[$scope])) {
            $this->setAttributes($data[$scope]);

            return true;
        } else {
            return false;
        }
    }

接下来看   setAttributes() :

    public function setAttributes($values, $safeOnly = true)
    {
        if (is_array($values)) {
            $attributes = array_flip($safeOnly ? $this->safeAttributes() : $this->attributes());
            //这里执行的是$this->safeAttributes()方法,该方法返回的是当前场景下需要验证的字段。最后$attributes打印下来看下图
            foreach ($values as $name => $value) {
                if (isset($attributes[$name])) {
                    $this->$name = $value;
                } elseif ($safeOnly) {
                    $this->onUnsafeAttribute($name, $value);
                }
            }
        }
    }

这里就会返回当前场景下需要验证的字段,涉及场景和规则,打印一下,其实就是返回的对应的就是表字段或者自定义属性字段。

array(2) {
["id"]=>
int(0)
["name"]=>
int(1)
}

在之后 执行的是 foreache循环  这里的$this 是那个$test 这个对象对象去调用 :

// 例如post 提交过来的数据是这样

$post=[

'id'=>123456,

'name'=>'lily'

] ;

$test->id=123456;

$test->name='lily';

所以这个load()方法只是分配post  或者get 发过来的数据,不做验证。

接下来看save(); 直接查看save方法源码 。

   public function save($runValidation = true, $attributeNames = null)
    {
        if ($this->getIsNewRecord()) {//判断是否是新纪录
            return $this->insert($runValidation, $attributeNames);//执行这里   之后$this代表的是test 这个模型表。                      
            //test 继承的是\yii\db\ActiveRecord   查看insert() 方法 。   
        } else {
            return $this->update($runValidation, $attributeNames) !== false; 
        } 
    }

继续跟踪 insert() 方法中:

    public function insert($runValidation = true, $attributes = null)
    {
        if ($runValidation && !$this->validate($attributes)) {//下面的代码分析validate方法 验证rules
            return false;
        }
        $result = $this->insertInternal($attributes);//保存数据

        return $result;
    }

或者跟踪update()方法:

    public function update($runValidation = true, $attributeNames = null)
    {
        if ($runValidation && !$this->validate($attributeNames)) {//下面的代码分析validate方法 验证rules
            return false;
        }

        return $this->updateInternal($attributeNames);//保存数据
    }

然后跟踪任意的 validate()方法:

   public function validate($attributeNames = null, $clearErrors = true)
    {
        if ($clearErrors) {
            $this->clearErrors();
        }

        if (!$this->beforeValidate()) { //在验证之前首先执行的是  beforValidata
            return false;
        }

        $scenarios = $this->scenarios();
        $scenario = $this->getScenario();//检查是否调用场景
        if (!isset($scenarios[$scenario])) {
            throw new InvalidArgumentException("Unknown scenario: $scenario");
        }

        if ($attributeNames === null) {
            $attributeNames = $this->activeAttributes();//返回数组(值为属性的名称)
        }

        $attributeNames = (array)$attributeNames;
        // $this->getActiveValidators() 验证数据。
        // 读取rules 方法 getActiveValidators() ->getValidators()->createValidators()
        // 这里验证rules等信息->createValidator()
        foreach ($this->getActiveValidators() as $validator) {
            $validator->validateAttributes($this, $attributeNames);
        }
        $this->afterValidate();//获取交集   检查是否有错误 hasError()

        return !$this->hasErrors();
    }

由此可知,调用save方法时,会自动调用validate方法,执行数据校验。随着数据验证完毕,之后就保存数据 。

全篇完。

你可能感兴趣的:(框架)