2015-10-12 37 views
1

LoginForm的:Yii2:的ActiveForm:在一個字段合併的規則/多個驗證

public function rules() 
{ 
    return [ 
     // username and password are both required 
     [['username', 'password'], 'required'], 
     // username should be a number and of 8 digits 
     [['username'], 'number', 'message'=>'{attribute} must be a number'], 
     [['username'], 'string', 'length' => 8], 
     // password is validated by validatePassword() 
     ['password', 'validatePassword'], 
    ]; 
} 

/** 
* Validates the password. 
* This method serves as the inline validation for password. 
* 
* @param string $attribute the attribute currently being validated 
* @param array $params the additional name-value pairs given in the rule 
*/ 
public function validatePassword($attribute, $params) 
{ 
    if (!$this->hasErrors()) { 
     $user = $this->getUser(); 
     if (!$user || !$user->validatePassword($this->password)) { 
      $this->addError($attribute, 'Incorrect username or password.'); 
     } 
    } 
} 

我已經建立了2個規則相同的字段,你可以在上面看到:

[['username'], 'number', 'message'=>'{attribute} must be a number'], 
[['username'], 'string', 'length' => 8], 

我想顯示以下3 方案的不同錯誤消息的形式情況

  1. 提供的值既不是數字,也不是8個字符(數字)。
  2. 提供的值是一個數字,但不是8個字符(數字)。
  3. 提供的值不是數字,而是8個字符(數字)。

我的問題是2倍:

A.有沒有一種辦法,這些規則在任何標準的結合,Yii2方式。
B. In my previous question我試圖設置一個自定義驗證器(解決這個問題的顯而易見的方法),但它被簡單地忽略了。我可以驗證的唯一方法是將username字段添加到場景中。但是,一旦我也添加了password,它又被忽略了。任何可以想到的原因? 編輯skipOnError = false在此行爲中完全沒有改變。

所以,請您在回答時,確保您最好在yii2/advanced;我幾乎沒有觸及默認設置,所以它應該很容易測試。

編輯:爲清楚起見,我想只允許有8個字符(數字)數字,這樣他們就可以潛在地具有領先0,例如。 0000000100000000。這就是爲什麼它必須是數字字符串。

+0

默認Yii2忽略驗證如果該值是空的(不像Yii1)。即使對空屬性也要執行驗證,請設置skipOnEmpty = false(與您的B.部分相關 - 忽略自定義驗證程序)。 – lubosdz

+0

@lubosdz對不起,但這並沒有改變任何行爲;我向用戶名添加了'skipOnEmpty = false',並且該字段是否爲空,如果場景中唯一的字段是'username'(在這種情況下,'validatePassword'驗證程序沒有'踢入)... – webeno

+0

'skipOnError'如何,也許這就是驗證者跳過的原因? – Beowulfenator

回答

2

爲不同情況組合規則並顯示自定義錯誤消息的最佳方法是創建自定義驗證程序。現在,如果你也想在客戶端工作(這是我上面提到的問題B中的一個問題,這要歸功於@Beowulfenator),您必須創建一個實際的自定義驗證器類yii2本地驗證器類。

下面是一個例子:

CustomValidator.php

<?php 

namespace app\components\validators; 

use Yii; 
use yii\validators\Validator; 

class CustomValidator extends Validator 
{ 
    public function init() { 
     parent::init(); 
    } 

    public function validateAttribute($model, $attribute) { 
     $model->addError($attribute, $attribute.' message'); 
    } 

    public function clientValidateAttribute($model, $attribute, $view) 
    { 
return <<<JS 
messages.push('$attribute message'); 
JS; 
    } 
} 

LoginForm.php

<?php 
namespace common\models; 

use Yii; 
use yii\base\Model; 
use app\components\validators\CustomValidator; 

/** 
* Login form 
*/ 
class LoginForm extends Model 
{ 
    public $username; 
    public $password; 
    public $custom; 

    private $_user; 


    /** 
    * @inheritdoc 
    */ 
    public function rules() 
    { 
     return [ 
      // username and password are both required 
      [['username', 'password'], 'required'], 
      // username should be a number and of 8 digits 
      [['username'], 'number', 'message'=>'{attribute} must be a number'], 
      [['username'], 'string', 'length' => 8], 
      // password is validated by validatePassword() 
      ['password', 'validatePassword'], 
      ['custom', CustomValidator::className()], 
     ]; 
    } 

    // ... 

的login.php

<?php 

/* @var $this yii\web\View */ 
/* @var $form yii\bootstrap\ActiveForm */ 
/* @var $model \common\models\LoginForm */ 

use yii\helpers\Html; 
use yii\bootstrap\ActiveForm; 

$this->title = 'Login'; 
?> 
<div class="site-login text-center"> 
    <h1><?php echo Yii::$app->name; ?></h1> 

    <?php $form = ActiveForm::begin([ 
     'id' => 'login-form', 
     'fieldConfig' => ['template' => "{label}\n{input}"], 
     'enableClientValidation' => true, 
     'validateOnSubmit' => true, 
    ]); ?> 

    <?= $form->errorSummary($model, ['header'=>'']) ?> 

    <div class="row"> 
     <div class="col-lg-4 col-lg-offset-4"> 
      <div class="col-lg-10 col-lg-offset-1"> 

        <div style="margin-top:40px"> 
         <?= $form->field($model, 'username') ?> 
        </div> 

        <div> 
         <?= $form->field($model, 'password')->passwordInput() ?> 
        </div> 

        <div> 
         <?= $form->field($model, 'custom') ?> 
        </div> 

        <div class="form-group" style="margin-top:40px"> 
         <?= Html::submitButton('Login', ['class' => 'btn btn-default', 'name' => 'login-button']) ?> 
        </div> 

      </div> 
     </div> 
    </div> 

    <?php ActiveForm::end(); ?> 

</div> 
0

Yii2忽略您的驗證規則可能是因爲您不僅複製了分類而且還複製了類型。 隨着數字驗證,我認爲你應該使用最小/最大選項來驗證數字長度。

對於這種情況:

'min'=>10000000,'max'=>99999999 
+0

對不起,但這不會允許數字'00000001'。正如我的問題所示,它必須是一個數字,並且是8個字符(數字)。 – webeno

2

最後,你需要這樣的:

  • 值需要
  • 值必須是8個字符
  • 的字符串值必須只包含數字

所以您應該簡單地嘗試:

['username', 'required'], 
['username', 'string', 'min' => 8, 'max' => 8], 
['username', 'match', 'pattern' => '/^[0-9]{8}$/', 'message'=>'{attribute} must be a number'], 
+0

這隻會顯示一個錯誤消息...我的目標是爲每個場景設置一個單獨的消息,正如我的問題所示... – webeno

+0

這裏有3條錯誤消息,但不完全是你問的(不是真的需要)。 – soju

+0

好的,忽略必需的,我不需要另外的消息...但是如果我添加一個字符串,例如3個字符,我只會得到消息,該值應該是一個數字,沒有關於它也應該是8個字符......如果設置一個自定義驗證器實際上工作(並且打敗我爲什麼它不會 - 在我原來的問題中看到問題_B_),我可以通過使用if語句來處理不同的情況... – webeno