Yii2 ActiveForm小部件渲染過程
問題:
(1)ActiveForm::begin()做了什麽,ActiveForm::end()做了什麽,中間echo的ActiveForm::field()內容是如何渲染的;
(2)我們在ActiveRecord模型類的rules規則裏定義的驗證方法如何在客戶端頁面同樣生效的;
首先看Yii2 ActiveForm小部件渲染過程
1. yii\widght\ActiveForm::begin($config);
這裏實例化了ActiveForm對象,通過 __construct() 調用 init(),在這裏生成小部件的唯一id:getId(),打開輸出緩沖:ob_start();ob_implicit_flush(false);
2. 小部件實例化後就可以通過它的field()方法生成表單內容控件
echo $form->field($model,$attribute,$options);//生成默認的textInput控件
echo $form->field($model,$attribute,$options)->radio();//生成radio控件
這裏有一個關鍵的地方:ActiveField對象在ActiveForm::field()方法中被創建,而其內容的渲染源自於`echo`的調用會觸發ActiveField的__toString()魔術方法,這裏調用了ActitveField的render()方法通過ActiveField的begin()與end()方法渲染完整內容。
(1) ActiveField::begin()會通過ActiveField::getClientOptions()方法獲得指定屬性的詳細信息,包括驗證規則,並填充到對應$form的$attributes屬性中。
(2) 這裏關鍵在於ActiveField::getClientOptions()做了什麽:
1)通過當前$model判斷該$attribute是否有效;
2)如果開啟了客戶端驗證,則通過$model->getActiveValidators($attribute)獲得與當前$attribute當前scenario相關的驗證規則;
3)遍歷上一步獲得的驗證規則,通過每個驗證器(yii\vaidators\Validator的子類的實例)的clientValidateAttribute()方法獲得對應驗證規則的客戶端驗證的js內容;
4)填充$attribute的id,name等信息後,將上一步獲得的所有客戶端驗證js內容組合到一個完整的js匿名函數中;
5)返回上述所有步驟獲得的信息,交由begin()存入對應$form的$attributes中。
(3) 當所有ActiveField都執行完畢,就來到了ActiveForm::end(),
1)通過ob_get_content()拿到上述所有field的輸出;
2)如果開啟了客戶端驗證,則會註入ActiveFormAsset資源包內容,並註入yii.activeForm.js的yiiActiveForm($attributes, $options);js內容。
(4) 頁面加載時會執行上面註入的yiiActiveForm.init()方法。
由於傳入的$attributes參數包含了所有$attribute的詳細描述與客戶端驗證需執行的js驗證方法,在yii.activeForm.js中就可以實現對各個屬性的事件監聽並觸發對應的驗證邏輯。
Yii2 ActiveForm小部件渲染過程