Grading System Validation using Yii2 - 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'],
];
}

Related

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.

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

yii2 custom validation addError message doesn't show

when i use custom validations on yii2 dynamic forms it doesn't show any error messages below the input field.Below I have posted my model.
It doesn't show any error messges when qty field gets validated
namespace frontend\models;
use Yii;
class OrderD extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'order_d';
}
public function rules()
{
return [
[['item_id', 'qty', 'price', 'value'], 'required'],
[['item_id'], 'integer'],
[['price', 'value'], 'number'],
[['order_code'], 'string', 'max' => 10],
[['item_id'], 'exist', 'skipOnError' => true, 'targetClass' => Item::className(), 'targetAttribute' => ['item_id' => 'id']],
[['order_code'], 'exist', 'skipOnError' => true, 'targetClass' => OrderH::className(), 'targetAttribute' => ['order_code' => 'code']],
['qty', 'validateQty']
];
}
public function validateQty($attribute)
{
$qty = $this->$attribute;
if ($qty >= 5)
{
$this->addError('qty', "qty validation successful");
}
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'item_id' => 'Item ID',
'order_code' => 'Order Code',
'qty' => 'Qty',
'price' => 'Price',
'value' => 'Value',
];
}
/**
* #return \yii\db\ActiveQuery
*/
public function getItem()
{
return $this->hasOne(Item::className(), ['id' => 'item_id']);
}
/**
* #return \yii\db\ActiveQuery
*/
public function getOrderCode()
{
return $this->hasOne(OrderH::className(), ['code' => 'order_code']);
}
}
Be sure to know custom validations are php functions and not convert as javascript to validate in runtime .. those will work after the page has submit and send to controller ..
here is simple sample you want :
['qty','custom_function_validation'],
];
}
public function custom_function_validation($attribute, $params){
if($this->$attribute>5){
$this->addError($attribute,'it\'s more than 5');
}
}
To create a validator that supports client-side validation, you should implement the yii\validators\Validator::clientValidateAttribute() method which returns a piece of JavaScript code that performs the validation on the client-side.
public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
// your validation
JS;
}
See the documentation here: http://www.yiiframework.com/doc-2.0/guide-input-validation.html#implementing-client-side-validation
Use method addError() in a controller and then just render your view file
Example
if ($promo_code) {
if ($promo_code->status == '1') {
$message = 'This combination is incorrect.';
$model->addError('promo_code', $message);
return $this->render('index', compact('model'));
}
$promo_code->status = '1';
$promo_code->save();
$model->save();
}

Setting default values on create and update in yii

I am trying to update some fields in yii 1.1 using the following rules, but it is not working.
public function rules()
{
return [
['CreatedOn','default','value'=>time(),'isEmpty'=>true,'on'=>'insert'],
['CreatedBy','default','value'=>\Yii::$app->user->identity->id,'isEmpty'=>true,'on'=>'insert'],
['ModifiedOn','default','value'=>time(),'isEmpty'=>true,'on'=>'update'],
['ModifiedBy','default','value'=>\Yii::$app->user->identity->id,'isEmpty'=>true,'on'=>'update'],
];
}
I am looking to update CreatedBy and CreatedOn when inserting, and ModifiedBy and ModifiedOn when updating.
From soju's excellent answer, with Yii2:
By default, a model supports only a single scenario named default
You should therefore set the scenario manually in your controller i.e:
$model->scenario = 'insert';
You could also use when instead of on i.e:
['CreatedOn', 'default', 'value'=>time(), 'isEmpty'=>true, 'when'=>
function($model) { return $model->isNewRecord; }
],
['ModifiedOn', 'default', 'value'=>time(), 'isEmpty'=>true, 'when'=>
function($model) { return !$model->isNewRecord; }
],
An alternative to setting them in rules() would be to use beforeSave() to set them:
public function beforeSave($insert) {
if ($insert) {
$this->CreatedBy = \Yii::$app->user->identity->id;
$this->CreatedOn = time();
} else {
$this->ModifiedBy = \Yii::$app->user->identity->id;
$this->ModifiedOn = time();
}
return parent::beforeSave($insert);
}
This is the correct way to do it:
Behaviors:
public function behaviors()
{
return [
'timestamp' => [
'class' => TimestampBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'created_on',
ActiveRecord::EVENT_BEFORE_UPDATE => 'modified_on',
ActiveRecord::EVENT_BEFORE_DELETE => 'deleted_at',
],
'value' => function () {
return date('Y-m-d H:i:s');
}
],
[
'class' => BlameableBehavior::className(),
'createdByAttribute' => 'created_by_id',
'updatedByAttribute' => 'updated_by_id',
],
];
}
If you need just a simple rule for default value, this is enough:
public function rules()
{
return [
['CreatedOn','default','value'=>time()],
['ModifiedOn','default','value'=>time(),'isEmpty'=>true],
...
]
}
The 'isEmpty'=>true option override the default isEmpty() function and returns true (it is always seen as empty) dues it is always populated with time()
For Yii2 version 2.0.8 from April 2016 I had an error with 'isEmpty'=>true because according to documentation it expects a function so you must to do like this:'isEmpty' => function ($value) {return true;}.
When you use this solution you get a value for ModifiedBy even on create and I believe that was not an intention. It is possible to write isEmpty to return true in case of an update but I simply used 'when' because it is much more readable for me. So, my solution for rules in a model was :
['CreatedBy', 'default', 'value' => Yii::$app->user->id],
['ModifiedBy', 'default', 'value' => Yii::$app->user->id,
'when' => function ($model) { return !$model->isNewRecord;}],
As a side note for this question is that for timestamps you should rely on database to fill them, CreatedOn with default value and a before update trigger for ModifiedOn.

Yii2 validation rule specific to a scenarios

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'],