Reputation: 9314
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]')
);
Upvotes: 1
Views: 2406
Reputation: 8964
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.
Upvotes: 1
Reputation: 540
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
}
Upvotes: 0