Set unique rule to a field on update action on yii2 rest - rest

I am creating a rest api with yii2 to create and update user information. Below is the rule function in the model class.
public function rules()
{
return [
[['name', 'emailId', 'contactNumber'], 'required'],
[['name', 'emailId', 'contactNumber'], 'string', 'max' => 255]
[['emailId', 'username', 'contactNumber'], 'unique'],
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]]
];
}
Here I mentioned emailId, username, contactNumber fields should be unique. When I try to create, it is checking whether the field is unique or not. if unique it is throwing the error else it is saving. That is fine.
But when I try to update the value there also it is checking the particular value for the field is unique or not. But it should not be like that. The unique validation should not work on update action. So I updated the rule with 'on'=>'update' as like Yii 1. Check the below function.
public function rules()
{
return [
[['name', 'emailId', 'contactNumber'], 'required'],
[['name', 'emailId', 'contactNumber'], 'string', 'max' => 255]
[['emailId', 'username', 'contactNumber'], 'unique', 'on'=>'update'],
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]]
];
}
But when i check the official documentation there is no option like on to check the particular action. When i use 'on'=>'update', both(while creating and update) places it is not validating. Might be because of the on. Just leave that. I need to add unique validation for those fields in create action only not in update action.
So, Please anybody help me with how to add unique validation to those fields only in create action.
Thanks.

You can set scenario for your REST actions in your ActiveController:
public function actions()
{
$actions = parent::actions();
$actions['update']['scenario'] = 'update';
$actions['create']['scenario'] = 'create';
return $actions;
}
And then use it in rules:
[['emailId', 'username', 'contactNumber'], 'unique', 'on'=>'create']
Also you must specify list of active attributes for each scenario in the particular model class:
public function scenarios()
{
$scenarios = parent::scenarios();
$scenarios['update'] = ['type', 'title', 'description'];
$scenarios['create'] = ['type', 'title', 'description', 'affiliate_id'];
return $scenarios;
}

Related

Laravel Backpack attribute accessor causing bug on update command

I am working on Laravel Backpack. I have two fields like this:
$this->crud->addField([ // SELECT2
'label' => 'Type',
'type' => 'select_from_array',
'name' => 'type',
'options' => [
'' => 'select type',
'Movie' => 'Movies',
'Series' => 'Series'
],
]);
$this->crud->addField([ // select2_from_ajax: 1-n relationship
'label' => "Entity", // Table column heading
'type' => 'select2_from_ajax',
'name' => 'entity_id', // the column that contains the ID of that connected entity;
'entity' => 'entity', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'data_source' => url('api/entity'), // url to controller search function (with /{id} should return model)
'placeholder' => 'Select', // placeholder for the select
'include_all_form_fields' => true, //sends the other form fields along with the request so it can be filtered.
'minimum_input_length' => 0, // minimum characters to type before querying results
'dependencies' => ['type'], // when a dependency changes, this select2 is reset to null
// 'method' => 'GET', // optional - HTTP method to use for the AJAX call (GET, POST)
]);
The second field options are dependent on the first one.
In my model, I have:
public function getEntityIdAttribute()
{
$id = $this->attributes['entity_id'];
$type = $this->attributes['type'];
if ($type == "Movie") {
$attribute = Movie::find($id);
} else {
$attribute = Series::find($id);
}
return $attribute->name;
}
Create and List operations work perfectly. But on update, it throws this error:
Undefined array key "entity_id"
Why is this accessor not working on the update? or can we somehow skip the accessor on the update command?

Laminas / ZF3: Add manually Error to a field

is it possible to add manually an Error Message to a Field after Field Validation and Input Filter ?
I would need it in case the Username and Password is wrong, to mark these Fields / Display the Error Messages.
obviously in ZF/ZF2 it was possible with $form->getElement('password')->addErrorMessage('The Entered Password is not Correct'); - but this doesnt work anymore in ZF3/Laminas
Without knowing how you do your validation (there are a few methods, actually), the cleanest solution is to set the error message while creating the inputFilter (and not to set it to the element after it has been added to the form).
Keep in mind that form configuration (elements, hydrators, filters, validators, messages) should be set on form creation and not in its usage.
Here the form is extended (with its inputfilter), as shown in the documentation:
use Laminas\Form\Form;
use Laminas\Form\Element;
use Laminas\InputFilter\InputFilterProviderInterface;
use Laminas\Validator\NotEmpty;
class Password extends Form implements InputFilterProviderInterface {
public function __construct($name = null, $options = []) {
parent::__construct($name, $options);
}
public function init() {
parent::init();
$this->add([
'name' => 'password',
'type' => Element\Password::class,
'options' => [
'label' => 'Password',
]
]);
}
public function getInputFilterSpecification() {
$inputFilter[] = [
'name' => 'password',
'required' => true,
'validators' => [
[
'name' => NotEmpty::class,
'options' => [
// Here you define your custom messages
'messages' => [
// You must specify which validator error messageyou are overriding
NotEmpty::IS_EMPTY => 'Hey, you forgot to type your password!'
]
]
]
]
];
return $inputFilter;
}
}
There are other way to create the form, but the solution is the same.
I also suggest you to take a look at the laminas-validator's documentation, you'll find a lot of useful informations
The Laminas\Form\Element class has a method named setMessages() which expects an array as parameter, for example
$form->get('password')
->setMessages(['The Entered Password is not Correct']);
Note that this will clear all error messages your element may already have. If you want to add your messages as in the old addErrorMessage() method you can do like so:
$myMessages = [
'The Entered Password is not Correct',
'..maybe a 2nd custom message'
];
$allMessages = array_merge(
$form->get('password')->getMessages(),
$myMessages);
$form
->get('password')
->setMessages($allMessages);
You can also use the error-template-name Laminas uses for its error messages as key in your messages-array to override a specific error message:
$myMessages = [
'notSame' => 'The Entered Password is not Correct'
];

Yii2 - Making dropdown list from db structure not the the inserted data in db

I have a form page that one of the field is named type and it's enum('lost', 'found') and in this form, I want that field to be a dropdown list that only has these two options lost and found.
one of the suggested options was using this in view
<?= $form->field($model, 'type')->dropDownList(
$items,
['prompt'=>'']
and this in the controller
$items = ArrayHelper::map(Ads::find()->all(), 'id', 'type');
but as you know it's just using the inserted data in the db and if I click on the dropdown list, it'll load all the lost and found options that are in the db.
Is there any way to tell yii to use the db structure and rules instead of the datas?
I have to point out that in the model I couldn't find any rules that is indicating the enum part, Is it ok? Why is it like this?
I used Gii for creating these.
public function rules()
{
return [
[['type', 'explanation', 'image', 'cost', 'province_id', 'address'], 'required'],
[['type', 'explanation', 'image', 'address'], 'string'],
[['cost'], 'integer'],
[['province_id'], 'string', 'max' => 20],
[['province_id'], 'exist', 'skipOnError' => true, 'targetClass' => Province::className(), 'targetAttribute' => ['province_id' => 'name']],
];
}
When a filed type is enum and generate crud from gii, yii generate this kind of dropdown in your form automatically.
<?= $form->field($model, 'type')->dropDownList([ 'lost' => 'Lost', 'found' => 'Found', ], ['prompt' => '']) ?>
In model its type is string:
public function rules()
{
return [
[['type'], 'string'],

After adding new column "name" to user table in yii2 advanced, data not getting saved in it

After assigning all required values to user model (column which i have added also). When I am using $model->save() data for all default attributes getting saved except the one I have added. I trying insert via REST call. If there is any other way to do please let me know. I have also followed this link https://github.com/dektrium/yii2-user/blob/master/docs/adding-new-field-to-user-model.md which is of no use.
this is my rules method in users model
public function rules()
{
return [
[['username', 'email'], 'filter', 'filter' => 'trim'],
[['username', 'email', 'status','name'], 'required'],
['email', 'email'],
['username', 'string', 'min' => 2, 'max' => 255],
// password field is required on 'create' scenario
['password', 'required', 'on' => 'create'],
// use passwordStrengthRule() method to determine password strength
$this->passwordStrengthRule(),
['username', 'unique', 'message' => 'This username has already been taken.'],
['email', 'unique', 'message' => 'This email address has already been taken.'],
];
}
Thank you.
User model which I was using extended from UserIdentity So I have added rules method in UserIdentity class but after adding new column to users table, that column should be specified in rules method of users model only which ever it might be extending. Previously there was no need of adding like this till Yii v2.1.0 may be in Yii 2.2.0 it has to be.

Duplicate Validation on Combined Fields in zend form

Hi there I have a table in which combination of three fields is unique. I want to put the check of duplication on this combination. Table looks like
I know how to validate single field, But how to validate the combination is not know. To validate one field I use the following function
public function isValid($data) {
// Options for name field validation
$options = array(
'adapter' => Zend_Db_Table::getDefaultAdapter(),
'table' => 'currencies',
'field' => 'name',
'message'=> ('this currency name already exists in our DB'),
);
// Exclude if a id is given (edit action)
if (isset($data['id'])) {
$options['exclude'] = array('field' => 'id', 'value' => $data['id']);
}
// Validate that name is not already in use
$this->getElement('name')
->addValidator('Db_NoRecordExists', false, $options
);
return parent::isValid($data);
}
Will any body guide me how can I validate duplication on combined fields?
There is no ready to use validator for this, as far as I know. You have either to write your own, or do a check with SQL-query with three conditions (one for each field).
you have to Apply a validation on name element of zend form.
Here is code for add validation on name field.
$name->addValidator(
'Db_NoRecordExists',
true,
array(
'table' => 'currencies',
'field' => 'name',
'messages' => array( "recordFound" => "This Currency Name already exists in our DB") ,
)
);
And you must set required true.