Yii2 validation rule specific to a scenarios - yii2

I have the following rules and scenarios
public function rules(){
return [
[['name','email','password'],'required'],
['email','myvalidation'],
['email','email'],
[['name', 'email', 'password'], 'required', 'on' => 'register'],
];
}
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['login'] = ['name','password','email'];//Scenario Values Only Accepted
return $scenarios;
}
I want the rule 'myvalidation' applied only to the login scenario and not at all in other cases.How this can be achieved in Yii2 ?

Remember you can also use "except". In example:
public function rules()
{
return [
[['first_name', 'email', 'phone', 'password'], 'required', 'except' => 'changepassword'],
[['password'], 'required', 'on' => 'changepassword']
]}

Just specify on property in this validation rule:
['email', 'myvalidation', 'on' => 'login'],

Related

Grading System Validation using Yii2

I am developiging a Grading System as shown below:
Model
public static function tableName()
{
return 'grade_item';
}
public function rules()
{
return [
[['grade_max', 'grade_min'], 'required'],
[['grade_max', 'grade_min'], 'number'],
];
}
How do I validate, probably from the Model between the grade_min and grade_max. Also, grade_min should not be greater that or equal to grade_max. I want to do it as shown in the diagram below. None of the contents of each row should be the same.
Use Compare validator
This validator compares the specified input value with another one and make sure if their relationship is as specified by the operator property.
public function rules()
{
return [
[['grade_max', 'grade_min'], 'required'],
[['grade_max', 'grade_min'], 'number'],
['grade_max', 'compare', 'compareAttribute' => 'grade_min', 'operator' => '>', 'type' => 'number'],
['grade_min', 'compare', 'compareAttribute' => 'grade_max', 'operator' => '<', 'type' => 'number'],
];
}

Yii2 rules work only use scenario

I write two scenario in Yii2 comment model, when user logged on or is guest.
my rules is:
public function rules()
{
return [
[['user_id'], 'required', 'on' => self::SCENARIO_USER],
[['name', 'email'], 'required', 'on' => self::SCENARIO_GUEST],
[['post_id', 'body', 'date'], 'required'],
[['user_id', 'parent_id', 'post_id', 'status'], 'integer'],
[['body'], 'string'],
[['date'], 'safe'],
[['name', 'email', 'site'], 'string', 'max' => 256],
];
}
and senarios funtion :
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_GUEST] = ['name' , 'email'];
$scenarios[self::SCENARIO_USER] = ['user_id'];
return $scenarios;
}
I use it as follows:
$commentModel = Yii::$app->user->isGuest ? new Comment(['scenario' => Comment::SCENARIO_GUEST]) : new Comment(['scenario' => Comment::SCENARIO_USER]);
if guest view form, only name and email checked and user fill form, no field checked !
why other rules don't check? how to fix it?
Refer Yii2 Scenarios
The scenarios() method returns an array whose keys are the scenario names and values the corresponding active attributes. An active attribute can be massively assigned and is subject to validation.
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_GUEST] = ['name' , 'email', 'date', 'body', 'site', 'post_id'];
$scenarios[self::SCENARIO_USER] = ['user_id', 'date', 'body', 'site', 'post_id'];
return $scenarios;
}
If you use scenarios() you need to define all attributes allowed to assign in given scenario. So if you want to allow guest to edit also body and date you need something like:
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_GUEST] = ['name' , 'email', 'body', 'date'];
$scenarios[self::SCENARIO_USER] = ['user_id'];
return $scenarios;
}
If you have many "shared" attributes between scenarios, you probably should not override this method and define it in rules() only.
See more in scenarios documentation.

Yii2 form validation - compare password repeat only when password field is filled

My form validation uses the following rules:
[['password', 'password_repeat'], 'required'],
['password_repeat', 'compare', 'compareAttribute' => 'password', 'message' => "Passwords don't match"],
How to write rules for password_repeat to compare it with password only if user fill password field. If user skip password, validation for password_repeat should be also skipped.
You can use scenarios for that:
public function rules() {
return [
[['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],
[['username', 'password', 'password_repeat'], 'required', 'on' => self::SCENARIO_REGISTER],
[
'password_repeat', 'compare', 'compareAttribute' => 'password',
'message' => "Passwords don't match", 'on' => self::SCENARIO_REGISTER,
],
];
}
This allows you to set different rules for different forms (different fields required on login and registration).
You may also consider creating different models for different forms with own rules(), like LoginForm and RegisterForm. This is actually more clean solution and gives more control.
EDIT
For conditional rules you should use when property:
public function rules() {
return [
[['password', 'password_repeat'], 'string'],
[
'password_repeat', 'compare', 'compareAttribute' => 'password',
'message' => "Passwords don't match", 'skipOnEmpty' => false,
'when' => function ($model) {
return $model->password !== null && $model->password !== '';
},
],
];
}

creation time is invalid when update in yii2

when I want to update form in yii2
It tells me this error
creation time is invalid -- update time is invalid
What do you think is it?
public function beforeSave($insert)
{
$date = new \DateTime();
$date->setTimestamp(time());
$date->setTimezone(new \DateTimezone('Istanbul'));
$this->update_time = $date->format('Y-m-d H:i:s');
if($this->isNewRecord)
$this->creation_time = $date->format('Y-m-d H:i:s');
return parent::beforeSave($insert);
}
My problem has been resolved
change date to safe in rules
[['creation_time', 'update_time'], 'safe'],
Your code is correct "Nader" but some time assigning the value not work so just remove the value or use this
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'create_time',
'updatedAtAttribute' => 'update_time',
//'value' => new Expression('NOW()'),
],
];
}
Just comment the value,
it will work.
For more detail https://www.yiiframework.com/doc/api/2.0/yii-behaviors-timestampbehavior
Just could just use the available TimestampBehavior behavior
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
use yii\db\ActiveRecord;
class Mymodel extends ActiveRecord{
public function behaviors() {
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'creation_time',
'updatedAtAttribute' => 'update_time',
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'creation_time',
ActiveRecord::EVENT_BEFORE_UPDATE => 'update_time',
],
'value' => new Expression('NOW()')
]
];
}
}
Remove any validation rules from your model you may have for this two attributes
creation_time and update_time

Capcha always show incorrect

I have used capcha in one of my forms. It always give verification code incorrect error.
Below is my code:
SchoolsController.php
public function actions() {
return [
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fontFile' => '#yii/captcha/SpicyRice.ttf',
'padding' => '0',
]
];
}
Model:
['verifyCode', 'captcha', 'captchaAction' => 'schools/captcha'],
View:
echo $form->field($modelSchoolRequestEarlyAccess, 'verifyCode')->widget(Captcha::className(), [
'options' => [
'placeholder' => 'Enter characters in the image',
'autocomplete' => 'off',
'maxlength' => 20
],
'captchaAction' => 'schools/captcha',
'template' => "<div class='field'><span><strong>*</strong>".Yii::t('frontend/quicksignup','VerifyCodeLabel').":</span></span>\n<div>{image}{input}<i class='refresh-code-icn' id='get-new-code'></i></div></div>"
])->label(false);
I have specified the captcha action as schools/captcha in model as well as view. But it always show verification incorrect.
What am I doing wrong??
You wrote SchoolController.php and your route is to schools. So you probably need to adjust your route to school/captcha
Did you add the rules?
public function rules()
{
$rules = parent::rules();
$rules[] = ['captcha', 'required'];
$rules[] = ['captcha', 'captcha'];
return $rules;
}