<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 輸入驗證 一般說來,程序猿永遠不應該信任從最終用戶直接接收到的數據,并且使用它們之前應始終先驗證其可靠性。 要給?[model](http://www.yiichina.com/doc/guide/2.0/structure-models)?填充其所需的用戶輸入數據,你可以調用 yii\base\Model::validate() 方法驗證它們。該方法會返回一個布爾值,指明是否通過驗證。若沒有通過,你能通過 yii\base\Model::errors 屬性獲取相應的報錯信息。比如, ~~~ $model = new \app\models\ContactForm; // 用用戶輸入來填充模型的特性 $model->attributes = \Yii::$app->request->post('ContactForm'); if ($model->validate()) { // 若所有輸入都是有效的 } else { // 有效性驗證失敗:$errors 屬性就是存儲錯誤信息的數組 $errors = $model->errors; } ~~~ `validate()`?方法,在幕后為執行驗證操作,進行了以下步驟: 1. 通過從 yii\base\Model::scenarios() 方法返回基于當前 yii\base\Model::scenario 的特性屬性列表,算出哪些特性應該進行有效性驗證。這些屬性被稱作?*active attributes*(激活特性)。 2. 通過從 yii\base\Model::rules() 方法返回基于當前 yii\base\Model::scenario 的驗證規則列表,這些規則被稱作?*active rules*(激活規則)。 3. 用每個激活規則去驗證每個與之關聯的激活特性。若失敗,則記錄下對應模型特性的錯誤信息。 ## 聲明規則(Rules) 要讓?`validate()`?方法起作用,你需要聲明與需驗證模型特性相關的驗證規則。為此,需要重寫 yii\base\Model::rules() 方法。下面的例子展示了如何聲明用于驗證?`ContactForm`?模型的相關驗證規則: ~~~ public function rules() { return [ // name,email,subject 和 body 特性是 `require`(必填)的 [['name', 'email', 'subject', 'body'], 'required'], // email 特性必須是一個有效的 email 地址 ['email', 'email'], ]; } ~~~ yii\base\Model::rules() 方法應返回一個由規則所組成的數組,每一個規則都呈現為以下這類格式的小數組: ~~~ [ // 必須項,用于指定那些模型特性需要通過此規則的驗證。 // 對于只有一個特性的情況,可以直接寫特性名,而不必用數組包裹。 ['attribute1', 'attribute2', ...], // 必填項,用于指定規則的類型。 // 它可以是類名,驗證器昵稱,或者是驗證方法的名稱。 'validator', // 可選項,用于指定在場景(scenario)中,需要啟用該規則 // 若不提供,則代表該規則適用于所有場景 // 若你需要提供除了某些特定場景以外的所有其他場景,你也可以配置 "except" 選項 'on' => ['scenario1', 'scenario2', ...], // 可選項,用于指定對該驗證器對象的其他配置選項 'property1' => 'value1', 'property2' => 'value2', ... ] ~~~ 對于每個規則,你至少需要指定該規則適用于哪些特性,以及本規則的類型是什么。你可以指定以下的規則類型之一: * 核心驗證器的昵稱,比如?`required`、`in`、`date`,等等。請參考[核心驗證器](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators)章節查看完整的核心驗證器列表。 * 模型類中的某個驗證方法的名稱,或者一個匿名方法。請參考[行內驗證器](http://www.yiichina.com/doc/guide/2.0/input-validation#inline-validators)小節了解更多。 * 驗證器類的名稱。請參考[獨立驗證器](http://www.yiichina.com/doc/guide/2.0/input-validation#standalone-validators)小節了解更多。 一個規則可用于驗證一個或多個模型特性,且一個特性可以被一個或多個規則所驗證。一個規則可以施用于特定[場景(scenario)](http://www.yiichina.com/doc/guide/2.0/structure-models#scenarios),只要指定?`on`?選項。如果你不指定?`on`?選項,那么該規則會適配于所有場景。 當調用?`validate()`?方法時,它將運行以下幾個具體的驗證步驟: 1. 檢查從聲明自 yii\base\Model::scenarios() 方法的場景中所挑選出的當前yii\base\Model::scenario的信息,從而確定出那些特性需要被驗證。這些特性被稱為激活特性。 2. 檢查從聲明自 yii\base\Model::rules() 方法的眾多規則中所挑選出的適用于當前yii\base\Model::scenario的規則,從而確定出需要驗證哪些規則。這些規則被稱為激活規則。 3. 用每個激活規則去驗證每個與之關聯的激活特性。 基于以上驗證步驟,有且僅有聲明在?`scenarios()`?方法里的激活特性,且它還必須與一或多個聲明自?`rules()`?里的激活規則相關聯才會被驗證。 ### 自定義錯誤信息 大多數的驗證器都有默認的錯誤信息,當模型的某個特性驗證失敗的時候,該錯誤信息會被返回給模型。比如,用 yii\validators\RequiredValidator 驗證器的規則檢驗?`username`?特性失敗的話,會返還給模型 "Username cannot be blank." 信息。 你可以通過在聲明規則的時候同時指定?`message`?屬性,來定制某個規則的錯誤信息,比如這樣: ~~~ public function rules() { return [ ['username', 'required', 'message' => 'Please choose a username.'], ]; } ~~~ 一些驗證器還支持用于針對不同原因的驗證失敗返回更加準確的額外錯誤信息。比如,yii\validators\NumberValidator 驗證器就支持 yii\validators\NumberValidator::tooBig 和 yii\validators\NumberValidator::tooSmall 兩種錯誤消息用于分別返回輸入值是太大還是太小。 你也可以像配置驗證器的其他屬性一樣配置它們倆各自的錯誤信息。 ### 驗證事件 當調用 yii\base\Model::validate() 方法的過程里,它同時會調用兩個特殊的方法,把它們重寫掉可以實現自定義驗證過程的目的: * yii\base\Model::beforeValidate():在默認的實現中會觸發 yii\base\Model::EVENT_BEFORE_VALIDATE 事件。你可以重寫該方法或者響應此事件,來在驗證開始之前,先進行一些預處理的工作。(比如,標準化數據輸入)該方法應該返回一個布爾值,用于標明驗證是否通過。 * yii\base\Model::afterValidate():在默認的實現中會觸發 yii\base\Model::EVENT_AFTER_VALIDATE 事件。你可以重寫該方法或者響應此事件,來在驗證結束之后,再進行一些收尾的工作。 ### 條件式驗證 若要只在某些條件滿足時,才驗證相關特性,比如:是否驗證某特性取決于另一特性的值,你可以通過 yii\validators\Validator::when 屬性來定義相關條件。舉例而言, ~~~ [ ['state', 'required', 'when' => function($model) { return $model->country == 'USA'; }], ] ~~~ yii\validators\Validator::when 屬性會讀入一個如下所示結構的 PHP callable 函數對象: ~~~ /** * @param Model $model 要驗證的模型對象 * @param string $attribute 待測特性名 * @return boolean 返回是否啟用該規則 */ function ($model, $attribute) ~~~ 若你需要支持客戶端的條件驗證,你應該配置 yii\validators\Validator::whenClient 屬性,它會讀入一條包含有 JavaScript 函數的字符串。這個函數將被用于確定該客戶端驗證規則是否被啟用。比如, ~~~ [ ['state', 'required', 'when' => function ($model) { return $model->country == 'USA'; }, 'whenClient' => "function (attribute, value) { return $('#country').value == 'USA'; }"], ] ~~~ ### 數據預處理 用戶輸入經常需要進行數據過濾,或者叫預處理。比如你可能會需要先去掉?`username`?輸入的收尾空格。你可以通過使用驗證規則來實現此目的。 下面的例子展示了如何去掉輸入信息的首尾空格,并將空輸入返回為 null。具體方法為通過調用?[trim](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#trim)?和?[default](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators.md#default)?核心驗證器: ~~~ [ [['username', 'email'], 'trim'], [['username', 'email'], 'default'], ] ~~~ 也還可以用更加通用的?[filter(濾鏡)](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#filter)?核心驗證器來執行更加復雜的數據過濾。 如你所見,這些驗證規則并不真的對輸入數據進行任何驗證。而是,對輸入數據進行一些處理,然后把它們存回當前被驗證的模型特性。 ### 處理空輸入 當輸入數據是通過 HTML 表單,你經常會需要給空的輸入項賦默認值。你可以通過調整?[default](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#default)?驗證器來實現這一點。舉例來說, ~~~ [ // 若 "username" 和 "email" 為空,則設為 null [['username', 'email'], 'default'], // 若 "level" 為空,則設其為 1 ['level', 'default', 'value' => 1], ] ~~~ 默認情況下,當輸入項為空字符串,空數組,或 null 時,會被視為“空值”。你也可以通過配置 yii\validators\Validator::isEmpty 屬性來自定義空值的判定規則。比如, ~~~ [ ['agree', 'required', 'isEmpty' => function ($value) { return empty($value); }], ] ~~~ > 注意:對于絕大多數驗證器而言,若其 yii\base\Validator::skipOnEmpty 屬性為默認值 true,則它們不會對空值進行任何處理。也就是當他們的關聯特性接收到空值時,相關驗證會被直接略過。在?[核心驗證器](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators)?之中,只有?`captcha`(驗證碼),`default`(默認值),`filter`(濾鏡),`required`(必填),以及?`trim`(去首尾空格),這幾個驗證器會處理空輸入。 ## 臨時驗證 有時,你需要對某些沒有綁定任何模型類的值進行?**臨時驗證**。 若你只需要進行一種類型的驗證 (e.g. 驗證郵箱地址),你可以調用所需驗證器的 yii\validators\Validator::validate() 方法。像這樣: ~~~ $email = 'test@example.com'; $validator = new yii\validators\EmailValidator(); if ($validator->validate($email, $error)) { echo '有效的 Email 地址。'; } else { echo $error; } ~~~ > 注意:不是所有的驗證器都支持這種形式的驗證。比如?[unique(唯一性)](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#unique)核心驗證器就就是一個例子,它的設計初衷就是只作用于模型類內部的。 若你需要針對一系列值執行多項驗證,你可以使用 yii\base\DynamicModel 。它支持即時添加特性和驗證規則的定義。它的使用規則是這樣的: ~~~ public function actionSearch($name, $email) { $model = DynamicModel::validateData(compact('name', 'email'), [ [['name', 'email'], 'string', 'max' => 128], ['email', 'email'], ]); if ($model->hasErrors()) { // 驗證失敗 } else { // 驗證成功 } } ~~~ yii\base\DynamicModel::validateData() 方法會創建一個?`DynamicModel`?的實例對象,并通過給定數據定義模型特性(以?`name`?和`email`?為例),之后用給定規則調用 yii\base\Model::validate() 方法。 除此之外呢,你也可以用如下的更加“傳統”的語法來執行臨時數據驗證: ~~~ public function actionSearch($name, $email) { $model = new DynamicModel(compact('name', 'email')); $model->addRule(['name', 'email'], 'string', ['max' => 128]) ->addRule('email', 'email') ->validate(); if ($model->hasErrors()) { // 驗證失敗 } else { // 驗證成功 } } ~~~ 驗證之后你可以通過調用 yii\base\DynamicModel::hasErrors() 方法來檢查驗證通過與否,并通過 yii\base\DynamicModel::errors 屬性獲得驗證的錯誤信息,過程與普通模型類一致。你也可以訪問模型對象內定義的動態特性,就像:?`$model->name`?和?`$model->email`。 ## 創建驗證器(Validators) 除了使用 Yii 的發布版里所包含的[核心驗證器](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators)之外,你也可以創建你自己的驗證器。自定義的驗證器可以是**行內驗證器**,也可以是**獨立驗證器**。 ### 行內驗證器(Inline Validators) 行內驗證器是一種以模型方法或匿名函數的形式定義的驗證器。這些方法/函數的結構如下: ~~~ /** * @param string $attribute 當前被驗證的特性 * @param array $params 以名-值對形式提供的額外參數 */ function ($attribute, $params) ~~~ 若某特性的驗證失敗了,該方法/函數應該調用 yii\base\Model::addError() 保存錯誤信息到模型內。這樣這些錯誤就能在之后的操作中,被讀取并展現給終端用戶。 下面是一些例子: ~~~ use yii\base\Model; class MyForm extends Model { public $country; public $token; public function rules() { return [ // 以模型方法 validateCountry() 形式定義的行內驗證器 ['country', 'validateCountry'], // 以匿名函數形式定義的行內驗證器 ['token', function ($attribute, $params) { if (!ctype_alnum($this->$attribute)) { $this->addError($attribute, 'token 本身必須包含字母或數字。'); } }], ]; } public function validateCountry($attribute, $params) { if (!in_array($this->$attribute, ['USA', 'Web'])) { $this->addError($attribute, 'The country must be either "USA" or "Web".'); } } } ~~~ > 注意:缺省狀態下,行內驗證器不會在關聯特性的輸入值為空或該特性已經在其他驗證中失敗的情況下起效。若你想要確保該驗證器始終啟用的話,你可以在定義規則時,酌情將 yii\validators\Validator::skipOnEmpty 以及 yii\validators\Validator::skipOnError 屬性設為 false,比如,?`````php [ > > ~~~ > ['country', 'validateCountry', 'skipOnEmpty' => false, 'skipOnError' => false], > ~~~ > > ]?````` ### 獨立驗證器(Standalone Validators) 獨立驗證器是繼承自 yii\validators\Validator 或其子類的類。你可以通過重寫 yii\validators\Validator::validateAttribute() 來實現它的驗證規則。若特性驗證失敗,可以調用 yii\base\Model::addError() 以保存錯誤信息到模型內,操作與?[inline validators](http://www.yiichina.com/doc/guide/2.0/input-validation#inline-validators)?所需操作完全一樣。比如, ~~~ namespace app\components; use yii\validators\Validator; class CountryValidator extends Validator { public function validateAttribute($model, $attribute) { if (!in_array($model->$attribute, ['USA', 'Web'])) { $this->addError($attribute, 'The country must be either "USA" or "Web".'); } } } ~~~ 若你想要驗證器支持不使用 model 的數據驗證,你還應該重寫 yii\validators\Validator::validate() 方法。你也可以通過重寫 yii\validators\Validator::validateValue() 方法替代?`validateAttribute()`?和?`validate()`,因為默認狀態下,后兩者的實現使用過調用?`validateValue()`實現的。 ## 客戶端驗證器(Client-Side Validation) 當終端用戶通過 HTML 表單提供相關輸入信息時,我們可能會需要用到基于 JavaScript 的客戶端驗證。因為,它可以讓用戶更快速的得到錯誤信息,也因此可以提供更好的用戶體驗。你可以使用或自己實現除服務器端驗證之外,**還能額外**客戶端驗證功能的驗證器。 > 補充:盡管客戶端驗證為加分項,但它不是必須項。它存在的主要意義在于給用戶提供更好的客戶體驗。正如“永遠不要相信來自終端用戶的輸入信息”,也同樣永遠不要相信客戶端驗證。基于這個理由,你應該始終如前文所描述的那樣,通過調用 yii\base\Model::validate() 方法執行服務器端驗證。 ### 使用客戶端驗證 許多[核心驗證器](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators)都支持開箱即用的客戶端驗證。你只需要用 yii\widgets\ActiveForm 的方式構建 HTML 表單即可。比如,下面的`LoginForm`(登錄表單)聲明了兩個規則:其一為?[required](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#required)?核心驗證器,它同時支持客戶端與服務器端的驗證;另一個則采用`validatePassword`?行內驗證器,它只支持服務器端。 ~~~ namespace app\models; use yii\base\Model; use app\models\User; class LoginForm extends Model { public $username; public $password; public function rules() { return [ // username 和 password 都是必填項 [['username', 'password'], 'required'], // 用 validatePassword() 驗證 password ['password', 'validatePassword'], ]; } public function validatePassword() { $user = User::findByUsername($this->username); if (!$user || !$user->validatePassword($this->password)) { $this->addError('password', 'Incorrect username or password.'); } } } ~~~ 使用如下代碼構建的 HTML 表單包含兩個輸入框?`username`?以及?`password`。如果你在沒有輸入任何東西之前提交表單,就會在沒有任何與服務器端的通訊的情況下,立刻收到一個要求你填寫空白項的錯誤信息。 ~~~ <?php $form = yii\widgets\ActiveForm::begin(); ?> <?= $form->field($model, 'username') ?> <?= $form->field($model, 'password')->passwordInput() ?> <?= Html::submitButton('Login') ?> <?php yii\widgets\ActiveForm::end(); ?> ~~~ 幕后的運作過程是這樣的:yii\widgets\ActiveForm 會讀取聲明在模型類中的驗證規則,并生成那些支持支持客戶端驗證的驗證器所需的 JavaScript 代碼。當用戶修改輸入框的值,或者提交表單時,就會觸發相應的客戶端驗證 JS 代碼。 若你需要完全關閉客戶端驗證,你只需配置 yii\widgets\ActiveForm::enableClientValidation 屬性為 false。你同樣可以關閉各個輸入框各自的客戶端驗證,只要把它們的 yii\widgets\ActiveField::enableClientValidation 屬性設為 false。 ### 自己實現客戶端驗證 要穿件一個支持客戶端驗證的驗證器,你需要實現 yii\validators\Validator::clientValidateAttribute() 方法,用于返回一段用于運行客戶端驗證的 JavaScript 代碼。在這段 JavaScript 代碼中,你可以使用以下預定義的變量: * `attribute`:正在被驗證的模型特性的名稱。 * `value`:進行驗證的值。 * `messages`:一個用于暫存模型特性的報錯信息的數組。 在下面的例子里,我們會創建一個?`StatusValidator`,它會通過比對現有的狀態數據,驗證輸入值是否為一個有效的狀態。該驗證器同時支持客戶端以及服務器端驗證。 ~~~ namespace app\components; use yii\validators\Validator; use app\models\Status; class StatusValidator extends Validator { public function init() { parent::init(); $this->message = '無效的狀態輸入。'; } public function validateAttribute($model, $attribute) { $value = $model->$attribute; if (!Status::find()->where(['id' => $value])->exists()) { $model->addError($attribute, $this->message); } } public function clientValidateAttribute($model, $attribute, $view) { $statuses = json_encode(Status::find()->select('id')->asArray()->column()); $message = json_encode($this->message); return <<<JS if (!$.inArray(value, $statuses)) { messages.push($message); } JS; } } ~~~ > 技巧:上述代碼主要是演示了如何支持客戶端驗證。在具體實踐中,你可以使用?[in](http://www.yiichina.com/doc/guide/2.0/tutorial-core-validators#in)?核心驗證器來達到同樣的目的。比如這樣的驗證規則:?`````php [ > > ~~~ > ['status', 'in', 'range' => Status::find()->select('id')->asArray()->column()], > ~~~ > > ]?`````
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看