Symfony 1.4 conditional validation - php

I have a Profile form that inherits from sfGuardRegisterForm
I have these fields:
$this->useFields(
array('first_name',
'last_name',
'email_address',
'country',
'language',
'current_password',
'new_password',
'password_again',
)
);
Required fields are:
email_address, country and language
And the conditions are:
If the email_address is not equal with the current email_address
then check if it's unique then save it
If the current_password is the actual password of the user then verify if new_password and password_again are equals and verify that the new_password is not equal to the actual password of the user
I just can't figure out in how implement this
EDIT
Thanks 1ed your example works but the problem is that I load the user Profile and I fill the fields: 'first_name', 'last_name', 'email_address', 'country', 'language' with the actual logged user so the email_address field will show the email address:
//...
$this->widgetSchema['email_address']->setDefault($this->_user->getEmailAddress());
//...
If the user dont change the email it will always show this message:
An object with the same "email_address" already exist.
I just want to skip that
Also this $this->getObject()->checkPassword() does not works, always show this message:
Incorrect current password.
I use:
$this->_user = sfContext::getInstance()->getUser()->getGuardUser();
To get actual user profile
EDIT2
Thanks again 1ed
This is very weird and I'm getting frustated, this is the situation
I have a "workaround" for this but it does not follow the standard, I can make it works but using sfContext::getInstance()->getUser()->getGuardUser(); and it will be more unnecesary code
If I use new ProfileForm($user) automatically fills all the fields, that's very good but I can't setDefault() I can't set null or empty any field so I can't use doUpdateObject() because this function only works when the current data is updated, also I have tested overriding bind(), save() etc. without results

email_address uniqueness: you should set unique: true in schema, in sfDoctrineGuardPlugin that's the case by default, so in BasesfGuardUserForm you should see a unique validator already: sfValidatorDoctrineUnique(array('model' => 'sfGuardUser', 'column' => array('email_address'))
current_password: you should create a callback type post validator for this
// in sfGuardRegisterForm::configure()
// these fields can be blank
$this->getValidator('current_password')->setOption('required', false);
$this->getValidator('new_password')->setOption('required', false);
$this->getValidator('password_again')->setOption('required', false);
// check the current password (this validator is not `required` by default)
$this->mergePostValidator(new sfValidatorCallback(array(
'callback' => array($this, 'checkPassword'),
), array(
'invalid' => 'Incorrect current password.'
)));
// add this method to the same form class
public function checkPassword(sfValidatorBase $validator, array $values, array $arguments)
{
// if a new password is given check whether the old one is correct or not and rise an error if not correct
if(0 != strlen($values['new_password']) && !$this->getObject()->checkPassword($values['current_password']))
{
throw new sfValidatorErrorSchema($validator, array(
'current_password' => new sfValidatorError($validator, 'invalid')
));
}
return $values;
}
Alternatively you can create a custom post validator, but I think it's not necessary.
EDIT:
If you would like to display empty email address just like the password fields add these to your form class:
// at form load remove the default value
protected function updateDefaultsFromObject()
{
parent::updateDefaultsFromObject();
if (isset($this['email_address']))
{
$this->setDefault('email_address', '');
}
}
// before save remove empty email address
protected function doUpdateObject($values)
{
if (isset($values['email_address']) && 0 == strlen($values['email_address']))
{
unset($values['email_address']);
}
parent::doUpdateObject($values);
}

I'll try and explain this in methodical terms instead of giving you a big block of code....
So first, you want to if (email_addr != current_email) and if that's true, go on to do
if (new_pass != current_pass) then follow on to make sure if (new_pass == new_pass_again)
Inside all of these IFs, you can return a true/false or some kind of flag, or just //do code inside the brackets :p
EDIT: encase these IFs in: if (country != NULL && language != NULL && email_addr != NULL)

Related

Unable to change value with codeIgniter validation

Here i have a list of contacts where user can add new contacts as well as edit them. Now at the add time i'm using server-side validation by codeIgniter for reduce redundancies. Also here i have a number of users that can add their contacts.
Suppose their are users named "John" and "Sara".
In this case, whenever "john" add new contact that are prevoiusly added by him, then it can't be add as duplicate contact number.
But whenever "john" add new contact that are previously added by "Sara", them it can be add . but its unable to add because CodeIgniter form_validation check unique value with entire table data.
Here is my Controller Code
$this->form_validation->set_rules('customer_email','Email', 'trim|check_email[customer.customer_email.' .$userId. ']', array('check_email' => 'Email must be unique.'));
$this->session->set_flashdata('check_email','Mobile must be unique');
$this->form_validation->set_rules('customer_mobile', 'Mobile', 'required|is_unique[customer.customer_mobile]');
$this->session->set_flashdata('contact_exists','Mobile must be unique');
if ($this->form_validation->run()) {
$userdata = $this->session->userdata();
$userId = $userdata['id'];
if (!$userId):
redirect(site_url());
endif;
I trying to many time but unable to fix this issue. I need your kind efforts. Thanks
Please find below solution.
First you need to remove unique check from customer_mobile.
$this->form_validation->set_rules('customer_mobile', 'Mobile', 'trim|required');
Once form_validation runs true then check customer_mobile with user in database and if it return row then return error else insert Contact.
if ($this->form_validation->run() == TRUE) {
// $check = Check here for customer_mobile with user in database
if($check):
return 'Contact already exist';
else:
// Insert Contact
endif;
}
Let me know if it not works.

Yii2: specific form field editable based on Role

Well, I can restrict users access permissions(i.e. view, create, update or delete) to forms or views based on access control using behaviors.
But I wonder how I can restrict a specific user from editing some of the fields in the form i.e. allow specific fields is read-only for some users and editable by some users.
Can I provide any kind of access rule in the model or attach some rule in the _form.php itself.
Thanks.
Try this.
if(\Yii::$app->user->can('admin')) {
$form->field($model,'field')->textInput();
}
In this case the input field will only appear if condition matches.
For exactly this case I've created my own class that extends ActiveForm. With the code below it's possible to add rules to a specific field for one or more roles. I use it like this in my forms:
<?= $form->field($model, 'foo', [], [AccessUtil::USER_ROLE => RoleBasedActiveForm::INVISIBLE]) ?>
The Role Based Active Form will show a normal input field when you don't add any rules. It won't display anything if you say it should be invisible for a roles and it also supports read-only (UNEDITABLE).
class RoleBasedActiveForm extends ActiveForm {
const VISIBLE = 0;
const INVISIBLE = 1;
const UNEDITABLE = 2;
public function field($model, $attribute, $options = [], $rules = []) {
$case = empty($rules) ? self::VISIBLE : $this->_validateRules($rules);
switch ($case) {
case self::VISIBLE:
return parent::field($model, $attribute, $options);
case self::INVISIBLE:
return;
case self::UNEDITABLE:
return parent::field($model, $attribute, array_merge($options, [
'template' => '{label}' . $model->$attribute,
]));
}
}
private function _validateRules($rules) {
// validate and return a const
}
}
This will do the form part. You will also have to do some validation after posting the values of course, to make sure someone hasn't modified the form. (changed read only to editable with the inspector or something)
Yes it can be done easily as far ur requirement is concerned without resorting to any utilities.
Try this code:
$form->field($model,'field')->textInput(['disabled' => !\Yii::$app->user->can('admin')]);
you need to replace ur field name and admin with your user role. In the above example only admin can edit this field, for other users it will show as disabled or readonly.
That's it.
This is a better answer. You put this in the validation either inline or as a separate function.
[[ 'input-name' ],
function ($attribute, $params) {
$user_role_array = Yii::$app->authManager->getRolesByUser(Yii::$app->user->getId());
if( !array_key_exists( "Role Name", $user_role_array ) ) {
$myOldA = ( $this->getOldAttribute( $attribute ) );
if( $this->{$attribute} !== (string) $myOldA ) {
$this->addError($attribute, "Please contact XXXXX to modify this option. The field has been reset. You may now resubmit the form" );
$this->{$attribute} = $myOldA;
} //End of if attribute equals old attribute
} //End of if array key exists
}, 'skipOnEmpty' => false, 'skipOnError' => false ],
[Next Rule if inline validation]

Laravel same validator

My case is for change password option. I already have current password in object $pass. I want to validate this $pass against textbox form input current_password to proceed to create a new password for the user. How to validate with same validator. Sorry I'm new to laravel.
$rules = array('password_current' => "required|same:$pass");
doesn't work.
since same: used to ensure that the value of current field is the same as another field defined by the rule parameter (not object). so you can't use this function take a look this example code below.
$data = Input::all();
$rules = array(
'email' => 'required|same:old_email',
);
the above code will check if current email field is same as old_email field.
so i think you can you simple if else
in your handle controller function assume
public function handleCheck(){
$current_password = Input::get('current_password');
$pass = //your object pass;
if($current_password == $pass){
// password correct , show change password form
}else{
// password incorrect , show error
}
}
let me know if it works. see Laravel Validation same
If you have password stored in $pass already just inject $pass in the request and use its field instead for e.g.
$request->request->add(['password_old' => $pass]);
Then, you can validate it like
$rules = array('password_current' => "required|same:password_old");

Laravel - both input values can't be no how to validate?

I'm using Laravel for a project and want to know how to validate a particular scenario I'm facing. I would like to do this with the native features of Laravel if this is possible?
I have a form which has two questions (as dropdowns), for which both the answer can either be yes or no, however it should throw a validation error if both of the dropdowns equal to no, but they can both be yes.
I've check the laravel documentation, but was unsure what rule to apply here, if there is one at all that can be used? Would I need to write my own rule in this case?
very simple:
let's say both the fields names are foo and bar respectively.
then:
// Validate for those fields like $rules = ['foo'=>'required', 'bar'=>'required'] etc
// if validation passes, add this (i.e. inside if($validator->passes()))
if($_POST['foo'] == 'no' && $_POST['bar'] == 'no')
{
$messages = new Illuminate\Support\MessageBag;
$messages->add('customError', 'both fields can not be no');
return Redirect::route('route.name')->withErrors($validator);
}
the error messge will appear while retrieving.
if you get confuse, just dump the $error var and check how to retrieve it. even if validation passes but it gets failed in the above code, it won't be any difference than what would have happened if indeed validation failed.
Obviously don't know what your form fields are called, but this should work.
This is using the sometimes() method to add a conditional query, where the field value should not be no if the corresponding field equals no.
$data = array(
'field1' => 'no',
'field2' => 'no'
);
$validator = Validator::make($data, array());
$validator->sometimes('field1', 'not_in:no', function($input) {
return $input->field2 == 'no';
});
$validator->sometimes('field2', 'not_in:no', function($input) {
return $input->field1 == 'no';
});
if ($validator->fails()) {
// will fail in this instance
// changing one of the values in the $data array to yes (or anything else, obvs) will result in a pass
}
Just to note, this will only work in Laravel 4.2+

CodeIgniter num_rows() not working?

Ok I don't know what's not working. I know my form validation is definitely working because all my other functions work properly, but I am setting messages whether it's true OR false and none of them show up so I feel like it's skipping right over the validation rule.. which is weird...
$this->form_validation->set_rules('region', 'required|valid_region');
The rule in MY_Form_validation.php in my libraries folder. The library IS loaded first. As I said all my other validations work properly such as my reCaptcha and everything.
function valid_region($str) {
$this->load->database();
if($this->db->query('SELECT id
FROM region
WHERE name = ?
LIMIT 1', array($str))->num_rows() == 0) {
//not a valid region name
$this->set_message('valid_region', 'The %s field does not have a valid value!');
return false;
}
$this->set_message('valid_region', 'Why is it validating?');
}
None of the messages will set so I have a feeling nothing is validating!
set_rules() function takes 3 parameters
The field name - the exact name you've given the form field.
A "human" name for this field, which will be inserted into the error message.
For example, if your field is named "user" you might give it a human
name of "Username". Note: If you would like the field name to be
stored in a language file, please see Translating Field Names.
The validation rules for this form field.
You put the validation rules as second parameter. That is why the validation is not running. Try this instead:
$this->form_validation->set_rules('region', 'Region', 'required|valid_region');
instead of
$this->form_validation->set_rules('region', 'required|valid_region');
try
$this->form_validation->set_rules('region', 'required|callback_valid_region');
when using custom validation rules you should use
callback to prepend the function name.
UPDATE
and use
$this->form_validation->set_message
instead of
$this->set_message
and in function valid_region
use return true when validation is successfull
$this->form_validation->set_rules('region', 'Region', 'required|valid_region');
function valid_region() {
$str = $this->input->post('name_of_input');
$this->load->database();
if($this->db->query('SELECT id
FROM region
WHERE name = ?
LIMIT 1', array($str))->num_rows() == 0) { // why compare "=" between `name` field and array() ?
//not a valid region name
$this->form_validation->set_message('valid_region', 'The %s field does not have a valid value!');
return false;
}
$this->form_validation->set_message('valid_region', 'Why is it validating?');
return true;
}

Categories