CodeIgniter Forums
Multiple Fields with a single callback using the form_validation library? - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forum-20.html)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forum-23.html)
+--- Thread: Multiple Fields with a single callback using the form_validation library? (/thread-16890.html)



Multiple Fields with a single callback using the form_validation library? - El Forum - 03-19-2009

[eluser]octavianmh[/eluser]
All-

I've been investigating this all day, looking for just a wee bit of sample code to set me on my way, but no luck so far.

My question: must I use separate validators for each field? Maybe there's something fundamental I'm not understanding about callbacks here, but since I need to check the database for both the username and password, I was hoping to check both from the same callback, and have a successful login processed by one, concise chunk of code.

So.. can I pass more than one field into a callback function? I assume I can via an array of some sort, but a nudge in the right direction, or "give up" would be helpful!

Thanks!


Multiple Fields with a single callback using the form_validation library? - El Forum - 03-19-2009

[eluser]drewbee[/eluser]
It's funny you should mention this, because I do exactly this. It really helps keep things a lot more organized.

Rules Array:
Code:
// Controller public page
function edit_profile()
{
    // ... snip ...
        $rules =  array(
                    array('field'     => 'timezone',
                          'label'     => 'Timezone',
                          'rules'     => 'required|callback__edit_profile[timezone]'
                      ),  
                    array('field'     => 'birth_month',
                          'label'     => 'Birth Month',
                          'rules'     => 'required|callback__edit_profile[birth_month]'
                      ),
                    array('field'     => 'birth_day',
                          'label'     => 'Birth Day',
                          'rules'     => 'required|callback__edit_profile[birth_day]'
                      ),
                    array('field'     => 'birth_year',
                          'label'     => 'Birth Year',
                          'rules'     => 'required|callback__edit_profile[birth_year]'
                      ),
                    array('field'    => 'display_age',
                          'label'    => 'Display Age',
                          'rules'    => 'callback__edit_profile[display_age]'
                      ),
                    array('field'    => 'country',
                          'label'    => 'Country',
                          'rules'    => 'callback__edit_profile[country]'
                      ),
                    array('field'    => 'state',
                          'label'    => 'State/Province',
                          'rules'    => 'callback__edit_profile[state]'
                      )
                );
                
        $this->form_validation->set_rules($rules);
    // ...snip. ...
}

When you are setting rules, callbacks allow you to pass a value to the function as the second parameter (which I have setup as $which). All you need to do is simply enclose what you are trying to do in brackets [ ]

Then my edit profile callback:
Code:
function _edit_profile($value = '', $which = '')
    {
        switch($which)
        {
            
            case 'timezone':
                if (!array_key_exists($value, $this->lookups['timezone']))
                {

                    $this->form_validation->set_message('_edit_profile', 'Invalid Timezone Selected');
                    return FALSE;
                }
            break;
            
            case 'birth_month':
                if (!array_key_exists($value, $this->lookups['birth_month']))
                {
                    $this->form_validation->set_message('_edit_profile', 'Invalid Month Selected');
                    return FALSE;
                }            
            break;
            
            case 'birth_day':
                if (!array_key_exists($value, $this->lookups['birth_day']))
                {
                    $this->form_validation->set_message('_edit_profile', 'Invalid Day Selected');
                    return FALSE;                    
                }
            break;
            
            case 'birth_year':
                if (!array_key_exists($value, $this->lookups['birth_year']))
                {
                    $this->form_validation->set_message('_edit_profile', 'Please enter a valid year ex. xxxx');
                    return FALSE;                    
                }            
            break;
            
            case 'display_age':
                if (!in_array($value, $this->lookups['display_age']))
                {
                    $this->form_validation->set_message('_edit_profile', 'Invalid value passed');
                    return FALSE;
                }
            break;
            
            case 'country':
                if (!array_key_exists($value, $this->lookups['countries']))
                {
                    $this->form_validation->set_message('_edit_profile', 'Invalid Country Selected');
                    return FALSE;                    
                }        
            break;
            
            case 'state':
                if (!array_key_exists($value, $this->lookups['states']))
                {
                    $this->form_validation->set_message('_edit_profile', 'Invalid State Selected');
                    return FALSE;                    
                }                
            break;
            
        }

        return TRUE;
    }

Hope this helps. Some people may raise the question of needing to pass a value and which validation to check. Simply use delimitors EX: set_rules> callback__edit_profile[state:32] and do a split in the callback.


Multiple Fields with a single callback using the form_validation library? - El Forum - 03-19-2009

[eluser]octavianmh[/eluser]
Great, incredibly helpful! Will post more questions soonish i'm sure. Smile

I would also submit that the documentation is a bit lacking in this area...using a single callback for multiple form fields seems an obvious thing to demonstrate!


Multiple Fields with a single callback using the form_validation library? - El Forum - 03-19-2009

[eluser]octavianmh[/eluser]
Huh, I can't find any doc references to: "$this->lookups" Where does it come from?


Multiple Fields with a single callback using the form_validation library? - El Forum - 03-19-2009

[eluser]drewbee[/eluser]
Sorry, don't take the code too literally. I cut it out of my edit profile controller.

That lookups variable holds all of the data returned from my model for populating the form (dropdowns / selection boxes); so that is something I do.

Do whatever validation you need too in between the cases.

This form is a massive form that takes in birth date, a lot of personal information, timezone, country etc. So as you can assume, lots of drop downs in there. I always verify that what they selected is an actual available value. Don't need people inserting their own stuff by making their own custom form.


Multiple Fields with a single callback using the form_validation library? - El Forum - 03-19-2009

[eluser]octavianmh[/eluser]
Ah! Gotcha, I was fearing there was some dark corner of PHP or CI that I'd never heard of. But I like the naming convention, may roll my own.. Wink


Multiple Fields with a single callback using the form_validation library? - El Forum - 05-29-2009

[eluser]MadZad[/eluser]
drewbee's posts got me thinking and experimenting, and I came across something unexpected and convenient for producing error messages when dealing with multiple fields in a custom validation function. distilled down, here's my setup:
Code:
$this->rules['bigfield'] = 'required';
$this->fields['bigfield'] = 'Big number';
$this->rules['smallfield'] = 'required|callback__not_more_than[bigfield]';
$this->fields['smallfield'] = 'Small number';

$this->validation->set_rules($this->rules);
$this->validation->set_fields($this->fields);

here's my callback function:
Code:
function _not_more_than($val, $check_field) {
    if ($val <= $_POST[$check_field]) return true;

    $this->validation->set_message('_not_more_than', "Error: '%s' is more than '%s'");
    return false;
}

From the docs, I did expect the first "%s" to turn into "Small number", but the second "%s" turned into "Big number". CI actually reaches into the fields array I fed set_fields to turn the callback's second parameter into the actual field name. Nice. That makes the error message:

Quote:Error: 'Small number' is more than 'Big number'

Disclaimer: $_POST has already been whitelisted and validated. Using the raw $_POST is verboten.