I'm writing something where if you select a certain button or dropdown I want to change the rules of a certain field. Basically the logic is, check a button or select an ID from a select and you don't need to populate the address fields. I've been trying to do thing within the form_validation rather than in he controller where I could actually do something like this
if(isset($_POST['checkbox'])){
//check rules
}
So I've done this:
public function check_address($str,$prefix=null){
$this->set_message('check_address','Please select an address or fill out a new one');
//var_dump($this->_field_data);exit;
$remove=array('address_line1','address_line2','address_line3','city','postcode');
if($prefix!==null){
foreach($remove as &$r){
$r=$prefix.'_'.$r;
}
}
unset($r);
foreach($this->_field_data as $key=>$f){
if(in_array($key,$remove)){
unset($this->_field_data[$key]);
}
}
}
This works the way I want it to but I think I've interfered with codeiginter's Form_Validation class as it throws an error stating the required indexes in my array are not set.
The error message
A PHP Error was encountered
Severity: Notice
Message: Undefined index: billing_address_line1
Filename: libraries/Form_validation.php
Line Number: 481
I'm not really too sure how I can achieve what I want to do without interfering with what codeigniter needs? Is there another array I need to remove so that the key isn't sort after?
I've also done this now
foreach($this->_field_data as $key=>&$f){
if(in_array($key,$remove)){
//unset($this->_field_data[$key]);
//str_replace('/required\|/','',$f['rules']);
//str_replace('/required/','',$f['rules']);
foreach($f['rules']as$r=>$val){
$val=strtolower($val);
if($val=='required')unset($f['rules'][$r]);
}
var_dump($f);
}
}
unset($f);
This now does what is required by removing the rule required but the required function I think must've already of run?
Array of rules
$this->con['validation']['checkout']=array(
array('field'=>'address_line1','label'=>'Address line 1','rules'=>'required|min_length[3]|max_length[200]|check_basket'),
array('field'=>'address_line2','label'=>'Address line 2','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'address_line3','label'=>'Address line 3','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'city','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[50]'),
array('field'=>'postcode','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[9]|valid_postcode'),
array('field'=>'shipping_addressID','label'=>'Address','rules'=>'check_address[]'),
array('field'=>'billing_address_line1','label'=>'Billing address line 1','rules'=>'required|min_length[3]|max_length[200]'),
array('field'=>'billing_address_line2','label'=>'Billing address line 2','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'billing_address_line3','label'=>'Billing address line 3','rules'=>'min_length[3]|max_length[200]'),
array('field'=>'billing_city','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[50]'),
array('field'=>'billing_postcode','label'=>'Town/City','rules'=>'required|min_length[3]|max_length[9]|valid_postcode'),
array('field'=>'billing_address_same','label'=>'Billing Address','rules'=>'check_address[billing]'),
array('field'=>'billing_addressID','label'=>'Billing address','rules'=>'check_address[billing]')
);
I think the simplest approach is the best. In the controller, add the rule if the checkbox is checked.
if(isset($_POST['checkbox'])){
$this->form_validation->set_rules('billing_address_line1', 'Billing Address Line 1', 'required');
}
Added after comments and question edited
Still striving for the simplest implementation while avoiding foreach loops using a bunch of string manipulation, and multiple rules arrays that are nearly identical.
This makes use of the fact that form_validation->set_rules() can accept an array in the third argument (instead of the pipe separated string). The string gets turned into an array eventually anyway so starting with an array is more efficient at runtime.
Also in the name of efficient runtime, method chaining is used when setting rules.
Start by creating reusable "rules" arrays to be passed to set_rules().
$rules_address1 = ['required', 'min_length[3]', 'max_length[200]', 'callback_check_basket'];
$rules_address_23 = ['min_length[3]', 'max_length[200]'];
$rules_city = ['required', 'min_length[3]', 'max_length[50]'];
$rules_postcode = ['required', 'min_length[3]', 'max_length[9]', 'callback_valid_postcode'];
$this->form_validation->set_message('required', 'You must provide {field}.');
$this->form_validation
->set_rules('address_line1', 'Address line 1', $rules_address1)
->set_rules('address_line2', 'Address line 2', $rules_address_23)
->set_rules('address_line3', 'Address line 3', $rules_address_23)
->set_rules('city', 'Town/City', $rules_city)
->set_rules('postcode', 'Postal Code', $rules_postcode);
if(!isset($_POST['checkbox']))
{
unset($rules_address1[0]);
unset($rules_address_23[0]);
unset($rules_city[0]);
unset($rules_postcode[0]);
}
$this->form_validation
->set_rules('billing_address_line1', 'Billing Address line 1', $rules_address1)
->set_rules('billing_address_line2', 'Billing Address line 2', $rules_address_23)
->set_rules('billing_address_line3', 'Billing Address line 3', $rules_address_23)
->set_rules('billing_city', 'Town/City', $rules_city)
->set_rules('billing_postcode', 'Postal Code', $rules_postcode);
I skipped rules for the addressID field(s) as I'm not sure how it is used.
Also, per CI SOP, added callback_ to what appeared to me to be custom callback methods. Adjust accordingly.
As you know, this all takes place in the controller before $this->form_validation->run() is called.
Check it from Form validation class. Call your own validation method for rules that you want to delete. https://codeigniter.com/user_guide/libraries/form_validation.html#callbacks-your-own-validation-methods
Then in those methods, check whether Checkbox is checked or not. If checked, skip all rules, and return TRUE from callback function. Something like this:
address_line1_callback_function() {
CI = &get_instance();
if ( CI->input->post('checked') )
return true;
/// Rules for address line go here
}
Related
I'm trying to make a validation for 2 field that must have a different value. I only know how to set the rules for validate matching value.
$this->form_validation->set_rules('book1','Book1','required|matches[book2]');
$this->form_validation->set_rules('book2','Book2','required|matches[book1]');
if I input book1=novel, and book2=novel, the code above will return TRUE.
How can I validate 2 field where the value of each field is not matching each other? So if I input book1=novel and book2=comic, it will return TRUE.
You should use callback_ method for custom validation, CI form validation library does not provide notMatch type validation rule, see below sample code.
$this->form_validation->set_rules('book1','Book1','required');
$this->form_validation->set_rules('book2','Book2','required|callback__notMatch[book1]');
AND place method in controller class
function _notMatch($book2Value, $book1FieldName){
if($book2Value != $this->input->post($book1FieldName){
$this->form_validation->set_message('_notMatch', 'book1 and book2 values are not matching');
return false;
}
return true;
}
In codeigniter 3 you can use the differs[] set rule, to enforce that field values don't match.
$this->form_validation->set_rules('book1', 'Book 1', 'required|differs[book2]');
$this->form_validation->set_rules('book2', 'Book 2', 'required|differs[book1]');
This means you don't need to create an unnecessary callback. However, for older versions you will.
See the documentations for more: Codeigniter 3 Documentation
You can use differs like so:
$this->form_validation->set_rules('password', 'current password', 'max_length[25]|min_length[5]|required');
$this->form_validation->set_rules('new_password', 'new password', 'max_length[25]|min_length[5]|required|differs[password]');
$this->form_validation->set_rules('confirm_password', 'confirm password', 'required|max_length[25]|min_length[5]|matches[new_password]');
I've used Codeigniter for a while and whilst I've not always found the form validation as straightforward as I'm sure it should be I've never had any massive problems... until now!
I have a simple form comprised of text inputs and a textarea. The form starts off prepopulated and, if the validation fails, repopulates it with the last changed state.
My problem is this - The textarea needs to accept pound signs (£). It populates text from the database absolutely fine but on submit, whether the form validates or not, it strips them out, regardless of what I do!!
I've scoured the net and can only find solutions about applying things like htmlentities to the validation rules, but if I firephp the post data out, even before the rules, it's already been stripped out.
global_xss_filtering is set to false in my config.
It's driving me mad and wasting way more time than it should... has anyone got a solution to this, I know I'm probably missing something really simple - it's maddening!
Thanks,
Helen
Here's my validation code, although the firephp log at the top shows it to already be stripped out so I can't see how doing anything here will help... I've tried adding the various php function as it suggests HERE (codeigniter manual) but it makes no difference at all.
public function edit_entry2($entry_id, $page_id) {
$this->firephp->log($_POST);
$this->load->library('form_validation');
$this->form_validation->set_rules('name', 'Name', 'required|max_length[255]');
$this->form_validation->set_rules('address1', 'Address line 1', 'max_length[255]');
$this->form_validation->set_rules('address2', 'Address line 2', 'max_length[255]');
$this->form_validation->set_rules('address3', 'Address line 3', 'max_length[255]');
$this->form_validation->set_rules('address4', 'Address line 4', 'max_length[255]');
$this->form_validation->set_rules('county', 'County', 'required|max_length[255]');
$this->form_validation->set_rules('post_code', 'Post Code', 'max_length[10]');
$this->form_validation->set_rules('telephone1', 'Telephone 1', 'required|max_length[12]|is_natural');
$this->form_validation->set_rules('telephone2', 'Telephone 2', 'max_length[12]|is_natural');
$this->form_validation->set_rules('fax', 'Fax', 'max_length[12]|is_natural');
$this->form_validation->set_rules('email', 'Email address', 'valid_email');
$this->form_validation->set_rules('website', 'Website', 'max_length[255]');
$this->form_validation->set_rules('rating_awards', 'Rating/Awards', 'max_length[255]');
$this->form_validation->set_rules('description', 'Description', 'max_length[1000]');
$this->form_validation->set_rules('categories[]', 'Categories', 'callback_categories_check');
if ($this->form_validation->run() == FALSE)
{
$this->edit_entry($entry_id, $page_id);
}
else
{
$updated_entry = array('name'=>$_POST['name'], 'address1'=>$_POST['address1'], 'address2'=>$_POST['address2'], 'address3'=>$_POST['address3'], 'address4'=>$_POST['address4'], 'county'=>$_POST['county'], 'post_code'=>$_POST['post_code'], 'telephone1'=>$_POST['telephone1'], 'telephone2'=>$_POST['telephone2'], 'fax'=>$_POST['fax'], 'email'=>$_POST['email'], 'website'=>$_POST['website'], 'rating_awards'=>$_POST['rating_awards'], 'description'=>$_POST['description']);
$this->tourism_catalogue_model->update_entry($entry_id, $updated_entry, $_POST['categories']);
$this->index($page_id);
}
}
You can use validation callbacks. So, when your validation rule is triggered, it will then fire a callback function that you could then use to strip out or inject the pound symbols as desired.
Form Validation Callbacks
I'd like to have input validated with form_validation class, that'll allow me to put numeric or empty value in the field.
Something like this:
$this->form_validation->set_rules('field[]','The field','numeric or empty|xss_clean');
Is this possible to achieve?
$this->form_validation->set_rules('field[]', 'The field', 'numeric|xss_clean');
This should be sufficient in theory, since the field hasn't been set to required.
But, it returns me the errors
Then perhaps an extra step:
if (!empty($this->input->post('field[]')))
{
$this->form_validation->set_rules('field[]', 'The field', 'numeric|xss_clean');
}
For phone number with 10 digits:
$this->form_validation->set_rules('mobile', 'Mobile Number ', 'required|regex_match[/^[0-9]{10}$/]'); //{10} for 10 digits number
I think you mean "Using Arrays as Field Names"
You can have a look at this page
$this->form_validation->set_rules('field[]','The field','is_natural|trim|xss_clean');
if ($this->form_validation->run() == FALSE) {
$errors = $this->form_validation->error_array();
if (!empty($errors['field'])) {
$errors_data = $errors['field'];
}
print_r($errors_data);exit;
}
You can use is_natural that Returns FALSE if the form element contains anything other than a natural number: 0, 1, 2, 3, etc.
For empty checking required rule is used that Returns FALSE if the form element is empty. So remove the required rule is if used.
And use form_validation rules for showing your rules message
In a form, I have the following element:
$email = new Zend_Form_Element_Text('username');
$email
->setLabel($this->getView()->l('E-mail'))
->setRequired(TRUE)
->addValidator('EmailAddress')
->addValidator('Db_NoRecordExists', true,
array(
'table' => 'pf_user',
'field' => 'email',
'messages' => array(
'recordFound' => 'This username is already registered',
)
))
->setErrorMessages(array(
'emailAddressInvalidFormat' => 'You must enter a valid e-mail',
'isEmpty' => 'You must enter an e-mail',
'recordFound' => 'This e-mail has already registered in out database'
));
$form->addElement($email)
the problem is that I always I get the same message "You must enter a valid e-mail" (the first one). Does anybody knows what is the mistake??
Actually, what you're doing is the following :
You set the errors on the element
Zend now thinks that the element did not validate correctly and that the first error is
"You must enter a valid e-mail"
When you display the form, since you set errors, Zend will find them and display the first one it finds. If you switch the order then you'll find that whichever error you put up top will be the error you get.
The more correct way is to set the custom messages in the validator. When the validators are called to validate the element, if the validation fails, the validator will call the setErrorMessages on the element to set the custom errors you specify. Use this type of code below to set your custom messages.
$element->addValidator( array( 'Db_NoRecordExists', true, array(
'messages' = array(
Zend_Validate_Db_Abstract::ERROR_NO_RECORD_FOUND => 'Myy custom no error record',
Zend_Validate_Db_Abstract::ERROR_RECORD_FOUND => 'My custom record error'
)
) ) );
You'll find that usually there are consts in each validator class that specify one type of error. In this case, the consts are in the parent class of the DB_NoRecordExists class but usually you'll find them directly in the class near the top.
Basically by passing 'true' as second parameter to addValidator() you are saying the validator to break the chain whenever validator fails . Since "" is not an valid email address hence the first email validator fails and breaks the chain
From Zend Doc http://framework.zend.com/manual/en/zend.validate.validator_chains.html
In some cases it makes sense to have a validator break the chain if
its validation process fails. Zend_Validate supports such use cases
with the second parameter to the addValidator() method. By setting
$breakChainOnFailure to TRUE, the added validator will break the chain
execution upon failure, which avoids running any other validations
that are determined to be unnecessary or inappropriate for the
situation. If the above example were written as follows, then the
alphanumeric validation would not occur if the string length
validation fails:
$validatorChain->addValidator(
new Zend_Validate_StringLength(array('min' => 6,
'max' => 12)),
true)
->addValidator(new Zend_Validate_Alnum());
Say I create a text element like this:
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->setRequired(true);
Whats the best way to change the default error message from:
Value is empty, but a non-empty value
is required
to a custom message? I read somewhere that to replace the message, just use addValidator(..., instead (NO setRequired), like this:
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->addValidator('NotEmpty', false, array('messages'=>'Cannot be empty'));
but in my testing, this doesn't work - it doesn't validate at all - it will pass with an empty text field. Using both (addValidator('NotEmp.. + setRequired(true)) at the same time doesn't work either - it double validates, giving two error messages.
Any ideas?
Thanks!
An easier way to set this "site-wide" would be to possibly do the following in a bootstrap or maybe a base zend_controller:
<?php
$translateValidators = array(
Zend_Validate_NotEmpty::IS_EMPTY => 'Value must be entered',
Zend_Validate_Regex::NOT_MATCH => 'Invalid value entered',
Zend_Validate_StringLength::TOO_SHORT => 'Value cannot be less than %min% characters',
Zend_Validate_StringLength::TOO_LONG => 'Value cannot be longer than %max% characters',
Zend_Validate_EmailAddress::INVALID => 'Invalid e-mail address'
);
$translator = new Zend_Translate('array', $translateValidators);
Zend_Validate_Abstract::setDefaultTranslator($translator);
?>
Give this a shot:
$firstName = new Zend_Form_Element_Text('firstName');
$firstName->setLabel('First Name')
->setRequired(true)
->addValidator('NotEmpty', true)
->addErrorMessage('Value is empty, but a non-empty value is required.');
The key is that "true" on the validator if you set that to true, it'll kill the other validations after it. If you add more than one validation method, but set that to false, it will validate all methods.
Zend_Form sets the required validation error as 'isEmpty', so you can override its message using setErrorMessages(). For example:
//Your Required Element
$element->setRequired(true)->setErrorMessages(array(
'isEmpty'=>'Please fill this field'
));
It worked for me, using ZF 1.11
Try
->addValidator('Digits', false);
or
->addValidator('Digits');
You assume that to check Digits it has to have a string length anyway.
Also, I like to do some custom error messages like this:
$firstName->getValidator('NotEmpty')->setMessage('Please enter your first name');
This allows you to "get" the validator and then "set" properties of it.
Try the following.
$subjectElement->setRequired(true)->addErrorMessage('Please enter a subject for your message');
This worked form me.
But try this:
$firstName->setRequired(true)
->addValidator('NotEmpty', false, array('messages' => 'bar'))
->addValidator('Alpha', false, array('messages'=>'Must contain only letters'));
If left empty and submitted, itll give two messages bar & '' is an empty string. Its that second message thats coming from setRequired(true) thats the problem
if you put:
$element->setRequired(false);
the validations don't work at all, you have to define:
$element->setAllowEmpty(false);
in order to get the correct behavior of the validations.
Try this..
$ausPostcode = new Zend_Form_Element_Text('aus_postcode'); $ausPostcode->setLabel('Australian Postcode')
->setRequired(true)
->addValidator('StringLength', false, array(4, 4))
->addValidator(new Zend_Validate_Digits(), false)
->getValidator('digits')->setMessage('Postcode can only contain digits');
This sets the custom error message only for the Digits validator.
One small issue. This code:
$zipCode->setLabel('Postal Code')
->addValidator('StringLength', true, array( 5, 5 ) )
->addErrorMessage('More than 5')
->addValidator('Digits', true)
->addErrorMessage('Not a digit');
Will generate both error messages if either validation fails. Isn't is supposed to stop after the first fails?
use a zend translator with zend_validate.php from
ZendFramework-1.11.3\resources\languages\en\Zend_Validate.php and then modify this file how you need
and then modify it accordingly to your needs