bashleigh
bashleigh

Reputation: 9314

Remove rule from codeigniter from MY_Form_validation

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

Answers (2)

DFriend
DFriend

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

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

Related Questions