Welcome Guest, Not a member yet? Register   Sign In
Form_validation: conditional requirement
#1

[eluser]oneos[/eluser]
Heyas,

I'm building a registration form for an event. One of my fields, 'postal_code', is only required if 'province' is not set to 'Outside Canada'. Unfortunately, the standard way Form_validation works, this doesn't seem to be possible.

I've set the rules via form_validation.php in config, and I'm defining the custom functions in MY_Form_validation.php:

Code:
array(
    'field' => 'postal_code',
    'label' => 'Postal Code',
    'rules' => 'check_postal'
),

Code:
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class MY_Form_validation extends CI_Form_validation {

        /**
         * Constructor
         */
        function __construct($rules = array())
        {
                parent::__construct($rules);
        }


        <snip>

        /**
         * Postal Code not blank if province not 'Outside Canada'
         *
         * @access      public
         * @param       string
         * @return      bool
         */
        function check_postal($str)
        {
                $this->set_message('check_postal', 'You must enter a Postal Code if within Canada.');

                if ($_POST['province'] !== 'ZZ' && trim($str) == '')
                        return FALSE;

                return TRUE;
        }

}


Now, this doesn't work. Form_validtion.php's run()/_execute() ditches empty fields and doesn't run them through rules unless they have the 'required' rule (I believe it also runs them through callbacks, being a potential fix here).

So, my question is -> What's the best way to get around this?, I've thought of a couple:

1: Move 'check_postal' into my controller, and use it as a callback. (can't seem to use it as a callback when it's defined in the library as it is).


2: Bring run() into MY_Form_validation, modifying what it does and doesn't ditch. This seems like a poor choice.
Code:
if (isset($_POST[$field]) AND $_POST[$field] != "")
{
    $this->_field_data[$field]['postdata'] = $_POST[$field];
}
To
Code:
if (isset($_POST[$field]) AND ($_POST[$field] != "" OR in_array('check_postal', $rule_array)))
{
    $this->_field_data[$field]['postdata'] = $_POST[$field];
}


3: Modify the field to some probably unique value in my controller prior to running validation.
Code:
// controller
if (trim($this->input->post('postal_code')) === '')
    $_POST['postal_code'] = '7FB6F0379';

if ( ! $this->form_validation->run() )
    ...

// MY_Form_validation.php
function check_postal($str)
{
    $this->set_message('check_postal', 'You must enter a Postal Code if within Canada.');

    if ($_POST['province'] !== 'ZZ' && $str == '7FB6F0379')
        return FALSE;

    return TRUE;
}


4: Similar to #1, except rather than moving the actual function over, just pass it along. Benefits from the callback being executed anyway, without the real function being out of place.
Code:
// controller
function _check_postal($str)
{
    return $this->check_postal($str);
}


So yeah, I'm leaning on #3 at this point. Any different thoughts on what would be best?
#2

[eluser]toopay[/eluser]
Custom validation (callback function), should be writen in your controller, not in the 'Form_validation' library.
#3

[eluser]theprodigy[/eluser]
What I've done in the past is, in my controller, where I set all the form_validation rules, I do an if statement on the value of what was submitted, and set the rules for the other field based on it:
Code:
$this->load->library('form_validation');

$this->form_validation->set_rules('field_1','Field 1', 'xss_clean|trim|required');

if($this->input->post('my_select') == 'value')
{
    $this->form_validation->set_rules('field_2','Field 2', 'xss_clean|trim|required');
}
else
{
    $this->form_validation->set_rules('field_2','Field 2', 'xss_clean|trim'); //not required, but still setting trim and xss_clean.
}
#4

[eluser]oneos[/eluser]
Alright, thanks.

I suppose I was trying to move some stuff out of the controller to lighten what's there, but yeah I suppose it would make more sense for it to be in the controller (given the function are related to the fields within it. I'll move them back in.

And thanks for the suggestion theprodigy, makes sense.




Theme © iAndrew 2016 - Forum software by © MyBB