Yii form model validation- either one is required

I have two fields on the form ( forgotpassword form ) username and email Id . User should enter one of them . I mean to retrieve the password user can enter user name or the email id . Could some one point me the validation rule for this ?

Is there any inbuilt rule I can use ?

( Sorry if it is already discussed or if I missed)

Thanks for your help

Regards

Kiran

Answers


I was trying to solve same problem today. What I've got is the code below.

public function rules()
{
    return array(
        // array('username, email', 'required'), // Remove these fields from required!!
        array('email', 'email'),
        array('username, email', 'my_equired'), // do it below any validation of username and email field
    );
}

public function my_required($attribute_name, $params)
{
    if (empty($this->username)
            && empty($this->email)
    ) {
        $this->addError($attribute_name, Yii::t('user', 'At least 1 of the field must be filled up properly'));

        return false;
    }

    return true;
}

General idea is to move 'required' validation to custom my_required() method which can check if any of field is filled up.

I see this post is from 2011 however I couldn't find any other solution for it. I Hope it will work for you or other in the future.

Enjoy.


Something like this is a bit more generic and can be reused.

public function rules() {
    return array(
        array('username','either','other'=>'email'),
    );
}
public function either($attribute_name, $params)
{
    $field1 = $this->getAttributeLabel($attribute_name);
    $field2 = $this->getAttributeLabel($params['other']);
    if (empty($this->$attribute_name) && empty($this->$params['other'])) {
        $this->addError($attribute_name, Yii::t('user', "either {$field1} or {$field2} is required."));
        return false;
    }
    return true;
}

Yii2

namespace common\components;

use yii\validators\Validator;

class EitherValidator extends Validator
{
    /**
     * @inheritdoc
     */
    public function validateAttributes($model, $attributes = null)
    {
        $labels = [];
        $values = [];
        $attributes = $this->attributes;
        foreach($attributes as $attribute) {
            $labels[] = $model->getAttributeLabel($attribute);
            if(!empty($model->$attribute)) {
                $values[] = $model->$attribute;
            }
        }

        if (empty($values)) {
            $labels = '«' . implode('» or «', $labels) . '»';
            foreach($attributes as $attribute) {
                $this->addError($model, $attribute, "Fill {$labels}.");
            }
            return false;
        }
        return true;
    }
}

in model:

public function rules()
{
    return [
        [['attribute1', 'attribute2', 'attribute3', ...], EitherValidator::className()],
    ];
}

I don't think there is a predefined rule that would work in that case, but it would be easy enough to define your own where for username and password fields the rule was "if empty($username . $password) { return error }" - you might want to check for a min length or other field-level requirements as well.


You can use private property inside model class for preventing displays errors two times (do not assign error to model's attribute, but only add to model without specifying it):

class CustomModel extends CFormModel
{
    public $username;
    public $email;

    private $_addOtherOneOfTwoValidationError = true;

    public function rules()
    {
        return array(
            array('username, email', 'requiredOneOfTwo'),
        );
    }

    public function requiredOneOfTwo($attribute, $params)
    {
        if(empty($this->username) && empty($this->email))
        {
            // if error is not already added to model, add it!
            if($this->_addOtherOneOfTwoValidationError)
            {
                $this->addErrors(array('Please enter your username or emailId.'));

                // after first error adding, make error addition impossible
                $this->_addOtherOneOfTwoValidationError = false;
            }

            return false;
        }

        return true;
    }
}

don't forget "skipOnEmpty" attr. It cost me some hours.

 protected function customRules()
{
    return [
              [['name', 'surname', 'phone'], 'compositeRequired', 'skipOnEmpty' => false,],
    ];
}

public function compositeRequired($attribute_name, $params)
{
    if (empty($this->name)
        && empty($this->surname)
        && empty($this->phone)
    ) {
        $this->addError($attribute_name, Yii::t('error', 'At least 1 of the field must be filled up properly'));

        return false;
    }

    return true;
}

This works for me:

            ['clientGroupId', 'required', 'when' => function($model) {
                return empty($model->clientId);
            }, 'message' => 'Client group or client selection is required'],

Need Your Help

Using the Parse iOS SDK with RubyMotion

ruby xcode parse-platform rubymotion

RubyMotion provides these instructions for vendoring 3rd party code: http://www.rubymotion.com/developer-center/guides/project-management/#_files_dependencies