mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-11-04 06:37:55 +08:00 
			
		
		
		
	Added yii\validators\EachValidator::$stopOnFirstError allowing addition of more than one error
				
					
				
			This commit is contained in:
		@ -88,6 +88,7 @@ Yii Framework 2 Change Log
 | 
			
		||||
- Enh #13074: Improved `yii\log\SyslogTarget` with `$options` to be able to change the default `openlog` options (timbeks)
 | 
			
		||||
- Enh #13122: Optimized query for information about foreign keys in `yii\db\oci` (zlakomanoff)
 | 
			
		||||
- Enh #13202: Refactor validateAttribute method in UniqueValidator (developeruz)
 | 
			
		||||
- Enh #13266: Added `yii\validators\EachValidator::$stopOnFirstError` allowing addition of more than one error (klimov-paul)
 | 
			
		||||
- Enh #13264: Added `yii\widgets\InputWidget::$field` field, allowing access to the related `yii\widget\ActiveField` instance (klimov-paul)
 | 
			
		||||
- Enh #13268: Added logging of memory usage (bashkarev)
 | 
			
		||||
- Enh: Added constants for specifying `yii\validators\CompareValidator::$type` (cebe)
 | 
			
		||||
 | 
			
		||||
@ -60,6 +60,15 @@ class EachValidator extends Validator
 | 
			
		||||
     * If disabled, own error message value will be used always.
 | 
			
		||||
     */
 | 
			
		||||
    public $allowMessageFromRule = true;
 | 
			
		||||
    /**
 | 
			
		||||
     * @var bool whether to stop validation once first error among attribute value elements is detected.
 | 
			
		||||
     * When enabled validation will produce single error message on attribute, when disabled - multiple
 | 
			
		||||
     * error messages mya appear: one per each invalid value.
 | 
			
		||||
     * Note that this option will affect only [[validateAttribute()]] value, while [[validateValue()]] will
 | 
			
		||||
     * not be affected.
 | 
			
		||||
     * @since 2.0.11
 | 
			
		||||
     */
 | 
			
		||||
    public $stopOnFirstError = true;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @var Validator validator instance.
 | 
			
		||||
@ -125,30 +134,35 @@ class EachValidator extends Validator
 | 
			
		||||
 | 
			
		||||
        $validator = $this->getValidator($model); // ensure model context while validator creation
 | 
			
		||||
 | 
			
		||||
        $originalErrors = $model->getErrors($attribute);
 | 
			
		||||
        $filteredValue = [];
 | 
			
		||||
        $detectedErrors = $model->getErrors($attribute);
 | 
			
		||||
        $filteredValue = $model->$attribute;
 | 
			
		||||
        foreach ($value as $k => $v) {
 | 
			
		||||
            $model->clearErrors($attribute);
 | 
			
		||||
            $model->$attribute = $v;
 | 
			
		||||
            if (!$validator->skipOnEmpty || !$validator->isEmpty($v)) {
 | 
			
		||||
                $validator->validateAttribute($model, $attribute);
 | 
			
		||||
            }
 | 
			
		||||
            $filteredValue[$k] = $model->$attribute;
 | 
			
		||||
            if ($model->hasErrors($attribute)) {
 | 
			
		||||
                $validationErrors = $model->getErrors($attribute);
 | 
			
		||||
                $model->clearErrors($attribute);
 | 
			
		||||
                if (!empty($originalErrors)) {
 | 
			
		||||
                    $model->addErrors([$attribute => $originalErrors]);
 | 
			
		||||
                }
 | 
			
		||||
                if ($this->allowMessageFromRule) {
 | 
			
		||||
                    $model->addErrors([$attribute => $validationErrors]);
 | 
			
		||||
                    $validationErrors = $model->getErrors($attribute);
 | 
			
		||||
                    $detectedErrors = array_merge($detectedErrors, $validationErrors);
 | 
			
		||||
                } else {
 | 
			
		||||
                    $model->clearErrors($attribute);
 | 
			
		||||
                    $this->addError($model, $attribute, $this->message, ['value' => $v]);
 | 
			
		||||
                    $detectedErrors[] = $model->getFirstError($attribute);
 | 
			
		||||
                }
 | 
			
		||||
                $model->$attribute = $value;
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
                if ($this->stopOnFirstError) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $model->$attribute = $filteredValue;
 | 
			
		||||
        $model->clearErrors($attribute);
 | 
			
		||||
        $model->addErrors([$attribute => $detectedErrors]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -155,4 +155,26 @@ class EachValidatorTest extends TestCase
 | 
			
		||||
        $validator->validateAttribute($model, 'attr_one');
 | 
			
		||||
        $this->assertEmpty($model->getErrors('attr_one'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @depends testValidate
 | 
			
		||||
     */
 | 
			
		||||
    public function testStopOnFirstError()
 | 
			
		||||
    {
 | 
			
		||||
        $model = FakedValidationModel::createWithAttributes([
 | 
			
		||||
            'attr_one' => [
 | 
			
		||||
                'one', 2, 'three'
 | 
			
		||||
            ],
 | 
			
		||||
        ]);
 | 
			
		||||
        $validator = new EachValidator(['rule' => ['integer']]);
 | 
			
		||||
 | 
			
		||||
        $validator->stopOnFirstError = true;
 | 
			
		||||
        $validator->validateAttribute($model, 'attr_one');
 | 
			
		||||
        $this->assertCount(1, $model->getErrors('attr_one'));
 | 
			
		||||
 | 
			
		||||
        $model->clearErrors();
 | 
			
		||||
        $validator->stopOnFirstError = false;
 | 
			
		||||
        $validator->validateAttribute($model, 'attr_one');
 | 
			
		||||
        $this->assertCount(2, $model->getErrors('attr_one'));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user