In YII2 validation rules I need something opposite to compare - yii2

I need to compare new password with old one that they are unequal
it`s a code where new password and password confirm compares, but what I can do for my matter?
['password_confirm', 'compare', 'compareAttribute'=>'password_new', 'message'=>"пароль и подтверждение пароля не совпадает" ],

I found a resolusion:
public function rules()
{
return [
['password_new', 'in', 'range' => [$this->password_current], 'not' => true, 'message'=>"new password equals with old one"]
];
}

Related

Yii2 : Require at least one of the two fields

One of the two phone numbers phone_parent or phone_students must be provided AND they must be an integer. When combined, only atLeastValidator works, when I leave it out, the integer works. Out of ideas. Any hint?
[['phone_parent', 'phone_student'], 'integer'],
['phone_student', AtLeastValidator::class, 'in' => ['phone_student', 'phone_parent']],
['phone_parent', AtLeastValidator::class, 'in' => ['phone_student', 'phone_parent']],
update: I've just discovered that integer works when I try to submit (no request is sent yet, I remain on form page); However it should work on focus out - just like all the other validators; It's an instance of ActiveForm.
I don't think you need to have that custom AtLeastValidator, you can use when and whenClient in the following way to work the way you want.
Your rules should look like below
[
['phone_parent'],
'required',
'when' => function ($model) {
return ($model->phone_student == '');
},
'whenClient' => 'function(attribute,value){
return ($("#testform-phone_student").val()=="");
}',
'message' => 'Either Parent or Student Phone must be filled',
],
[
['phone_student'],
'required',
'when' => function ($model) {
return ($model->phone_parent == '');
},
'whenClient' => 'function(attribute,value){
return ($("#testform-phone_parent").val()=="");
}',
'message' => 'Either Parent or Student Phone must be filled',
],
[['phone_parent', 'phone_student'], 'integer'],
Above all i would use a regular expression in order to validate the phone number to be valid rather than just using integer that will allow 0 as a pone number or mobile number which isnt valid. using match validator with a regex in the pattern will make it solid.

Yii2 validation message doesn't change

I have simple ajax validation for email.
$rules[] = [['email'], 'unique', "message"=>"Email адресът {value} вече съществува!"];
But my custom message doesn't show. It always return default message: This email address has already been taken. Any clue why is this? I thought it is as simple as that.Where i am wrong? Btw it is user dektrium module if that matters.Thank you in advance!
You should return the values in
public function rules()
{
return [
[['email'], 'unique', "message"=>"Email адресът {value} вече съществува!"];
// the email attribute should be a valid email address
['email', 'email'],
];
}
eventually you should extend or redefine the User Model rules() function

targetAttribute (Or something similar) for required validator (Yii2)

So, here is my scenario. I have got a model called URL. URL has the following attributes: link (required), scheme (required, but not safe.scheme is parsed from the link) and a few other attributes as well, which are not in context to this question.
Now, I made a custom validator for the scheme, which is following:
public function validateScheme($attribute, $param) {
if(empty($this->scheme)){
$this->addError('link', Yii::t('app', 'This is an invalid URL.'));
}
if (!in_array($this->scheme, $this->allowedSchemes)) {
$this->addError('link', Yii::t('app', 'This is an invalid URL.'));
}
}
Rules for URL:
public function rules() {
return [
['link', 'required', 'message' => Yii::t('app', 'URL can\'t be blank.')],
[['link'], 'safe'],
[['link'], 'string'],
['scheme', 'validateScheme']
];
}
This works fine when an invalid scheme is encountered, for example like let's say ftp.
However, when a completely invalid URL is entered, the scheme remains empty and the validateScheme is never triggered as, attribute scheme is not required. To verify, I called $model->validate() and it returns true even if it should not (or should may be, because the attribute is not required anyway).
So, my question number 2 : Is there a way to force the validateScheme be triggered no matter if the attribute is empty, or non empty? I do not seem to find a way to do this in documentation.
I then tried the other way around, and made scheme a required field. The problem with that is the fact that scheme field is not safe and not there in the form. So, the URL does not save, but no error is shown.
My question number 1, in that case would be: Is there a way to assign targetAttribute for scheme so that the error message is shown below link?
P.S. I know I can do this in the controller. I do not want to do that. I want to use the model only.
Another solution is, instead of having a default value, you could enable verify on empty (by default, it does not validate empty and not required fields). Something like this:
public function rules() {
return [
['link', 'required', 'message' => Yii::t('app', 'URL can\'t be blank.')],
[['link'], 'string'],
['scheme', 'validateScheme', 'skipOnEmpty' => false]
];
}
See more here.
Okay, setting a default value in the rules() solved my problem. The modified rules():
public function rules() {
return [
['link', 'required', 'message' => Yii::t('app', 'URL can\'t be blank.')],
[['link'], 'safe'],
[['link'], 'string'],
['scheme', 'default', 'value' => 0],
['scheme', 'validateScheme']
];
}

CakePHP 3 Auth on model other than User

I'm working on a project rebuild using CakePHP, and following the new Authentication documentation here:
http://book.cakephp.org/3.0/en/controllers/components/authentication.html
From what I'm reading, Cake3 uses the userModel='User' by default, but it has the option to set it to whatever you want. In my case, I have all the auth data in the 'Account' model (i.e. userModel => 'Account').
So, in my Account Entity, I added the following code:
protected function _setPassword($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
Additionally, in my accounts table, my 'passwd' field is set to varchar(255) [I've read that's required for some reason].
When I use my default baked 'add' and 'edit' methods, the password is stored in plain text, and not hashed. The ONLY way I've found to get around this is to create a custom method in the AccountsTable class then call it using this kludge:
$this->request->data['passwd'] = $this->Accounts->hashPassword($this->request->data['passwd']);
My Auth component looks like this...
$this->loadComponent('Auth', [
'loginAction' => [
'controller' => 'Accounts',
'action' => 'login'
],
'authError' => 'Unauthorized Access',
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'username',
'password' => 'passwd'
],
'userModel'=>'Accounts'
]
]
]);
Is there a way to do this without dinking around with the raw request data?
Your mutator is named wrongly, the convention for mutators is _set followed by the camel cased field/property name. So since your field name is passwd, not password, it has to be named _setPasswd instead.
protected function _setPasswd($password)
{
return (new DefaultPasswordHasher)->hash($password);
}
See also Cookbook > Entities > Accessors & Mutators

How to add current timestamp in the database. What is the format?

I want to add the current system time into database while inserting new record into database as in "time_created" column. PHP's time() function don't have support in yii2. I want yii2 specific time function that will help me save current timestamp. Anyone knows????
You can use yii\db\Expression to perform SQL function
<?php
use yii\db\Expression;
$model->time_created = new Expression('NOW()');
$model->save();
You can also use Yii2's formatter like below:
Yii::$app->formatter->asTimestamp(date('Y-d-m h:i:s')); //1410488596
Yii::$app->formatter->asDatetime(date('Y-d-m h:i:s')); //Sep 12, 2014, 2:21:56 AM
Yii 2 has special behavior for this. Just attach it to the model.
Add this to your model to behaviors() method:
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
public function behaviors()
{
return [
// Other behaviors
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'time_created',
'updatedAtAttribute' => false,
'value' => new Expression('NOW()'),
],
];
}
Maybe this is old but it may help some one else. Add the below code in your model. Make sure you change the createdAttribute to your attribute. You also have to include:
use yii\behaviors\TimestampBehavior;
use yii\db\Expression;
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'entry_date',
'updatedAtAttribute' => false,
'value' => new Expression('NOW()'),
],
];
}
You can Simply use PHP's date() function as - date('Y-m-d H:i:s');
There are several ways of adding timestamp, I suggest using UNIX timestamp for sake of dealing with timezone. For example in Google SQL instances you cannot setup timezone, but offset, which means that you would need to update offset twice a year because of summer/winter time. For that as someone mentioned you can also use behaviours:
public function behaviors()
{
return [
[
'class' => AttributeBehavior::className(),
'attributes' => [
ActiveRecord::EVENT_BEFORE_INSERT => 'entry_date',
],
'value' => function ($event) {
return time();
},
],
];
}
or you can simply just add before insert, like $model->entry_date=time(); but as you will do this on every INSERT then behaviors are better choice.
And of course if you want to read formatted date, you can use:
\Yii::$app->formatter->asDate($model->entry_date);
For asDate formatter, you can read here:
http://www.yiiframework.com/doc-2.0/yii-i18n-formatter.html#asDate()-detail