Yii2的場景如何理解

1.關於場景(scenarios)這個問題,開始搜了很多文章,看了其實有點容易被誤導,所以我推薦可以的話可以看一看源碼。

2.直接先給結論:

在大多數情況下,是不需要重寫 scenarios() 的。通過配置 rules() 來改變 scenarios() 的返回值,而不是直接手動覆蓋 sceanrios().覆蓋帶來的一個明顯的弊端是:你的精力被分散到了兩個方法內(rules() 和 scenarios()).

3.推薦文章如下:

yiichina.com/question/3042?sort=desc 

4.你可以把scenarios源碼複製到子類當中進行修改觀看這個scenarios()是怎麼工作的。

step1.這是我的rules()函數:

public function rules()
    {
        return [
            [['user_id', 'create_time'], 'integer'],
            [['content', 'picture_url'], 'string', 'max' => 128],
            [['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']],
            [['imageFile'],'file','skipOnEmpty'=>false,'extensions'=>'png,jpg','on'=> 
             ['create']],
        ];
    }

 

step2. 我把scenarios()源碼複製到了子類當中,方便修改:class Friend extends \yii\db\ActiveRecord{ }

class Friend extends \yii\db\ActiveRecord
{
 /***/
public function scenarios()
    {
        $scenarios = [self::SCENARIO_DEFAULT => []];
        foreach ($this->getValidators() as $validator) {
            foreach ($validator->on as $scenario) {
                $scenarios[$scenario] = [];
            }
            foreach ($validator->except as $scenario) {
                $scenarios[$scenario] = [];
            }
        }
        $names = array_keys($scenarios);
        
        //這四句是我自己調試的內容
        echo "第一步把rules()中所有場景都找出來:";
        echo "<pre>";     
        print_r($names);
        echo "<br><br>";

        foreach ($this->getValidators() as $validator) {
            if (empty($validator->on) && empty($validator->except)) {
                foreach ($names as $name) {
                    foreach ($validator->attributes as $attribute) {
                        $scenarios[$name][$attribute] = true;
                    }
                }
            } elseif (empty($validator->on)) {
                foreach ($names as $name) {
                    if (!in_array($name, $validator->except, true)) {
                        foreach ($validator->attributes as $attribute) {
                            $scenarios[$name][$attribute] = true;
                        }
                    }
                }
            } else {
                foreach ($validator->on as $name) {
                    foreach ($validator->attributes as $attribute) {
                        $scenarios[$name][$attribute] = true;
                    }
                }
            }
        }



        foreach ($scenarios as $scenario => $attributes) {
            if (!empty($attributes)) {
                $scenarios[$scenario] = array_keys($attributes);
            }
        }

        //這五句是我自己調試的內容
        echo "第二步把每個場景的的內容都對應上去:";
        echo "<pre>";     //第二步把每個場景的的內容都對應上去
        print_r($scenarios);
        echo "<br><br>";
        exit(0);

        return $scenarios;
    }
}

結果輸出如下:

雖然代碼裏面有很多個foreach,其實你可以理解爲就幹了上面兩件事。

第一步,找出rules()中所有的場景,也就是'on'=>['場景'],default是默認場景。

第二步,把場景對映的驗證屬性添加到數組裏面;

如果一個屬性,不開啓 on 的話,就默認屬於每一個場景。這句話很重要。你可以發現,上面 imageFile開啓了 'on'=>['create']

所以default場景就不會去驗證imageFile屬性,所以我在創建一條新內容的地方調用create場景:

這時候就回去驗證照片有沒有上傳;

而我更新的時候不設置場景,會採用默認場景,所以你可以發現默認場景裏面不需要驗證imageFile這一項的屬性,所以直接更改文字內容就可以了,不會因爲沒有上傳照片而無法通過驗證。 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章